Obsidian MCP + wyszukiwanie hybrydowe: dokumentacja referencyjna 2026
# Do podstaw aplikacji należy używać oficjalnej dokumentacji Obsidian; do MCP, wyszukiwania hybrydowego i indeksowania vaultu AI Blake’a z 16 894 plikami — jego materiałów referencyjnych.
Obsidian nie jest aplikacją do notatek. To lokalny w pierwszej kolejności, tekstowy korpus markdown o strukturze grafu, który po dodaniu infrastruktury wyszukiwania staje się rezerwuarem kontekstu dla AI. 16 894 pliki. 49 746 fragmentów. Zapytania w 23 ms. Zero wywołań API. Jeden plik SQLite o rozmiarze 83 MB. Ten przewodnik omawia cały system: od architektury skarbca, przez hybrid retrieval, po integrację z MCP i workflow operacyjne.
Najważniejsze wnioski
Inżynieria kontekstu, nie robienie notatek. Wartość vaulta Obsidian dla AI nie tkwi w samych notatkach, lecz w warstwie wyszukiwania, która umożliwia ich odpytywanie. Vault z 16 000 plików bez wyszukiwania jest bazą danych tylko do zapisu. Vault z 200 plikami, wyszukiwaniem hybrydowym (hybrid retrieval) i integracją MCP jest bazą wiedzy AI. Infrastrukturą wyszukiwania jest produkt. Notatki są surowcem.
Wyszukiwanie hybrydowe przewyższa wyszukiwanie wyłącznie po słowach kluczowych lub wyłącznie semantyczne. BM25 wychwytuje dokładne identyfikatory i nazwy funkcji. Wyszukiwanie wektorowe wychwytuje synonimy i dopasowania koncepcyjne mimo różnej terminologii. Reciprocal Rank Fusion (RRF) łączy oba podejścia bez konieczności kalibracji wyników. Żadna z tych metod sama nie obejmuje obu trybów awarii. Badania nad rankingiem fragmentów MS MARCO potwierdzają ten wzorzec: wyszukiwanie hybrydowe konsekwentnie przewyższa każdą z tych metod stosowaną osobno.3 Dogłębna analiza hybrid retriever omawia matematykę RRF, przepracowane przykłady z rzeczywistymi liczbami, analizę trybów awarii oraz interaktywny kalkulator fuzji.
MCP daje narzędziom AI bezpośredni dostęp do vaulta. Serwery Model Context Protocol (MCP) udostępniają retriever jako narzędzie, które Claude Code, Codex CLI, Cursor i inne narzędzia AI mogą wywoływać bezpośrednio. Agent odpytuje vault, otrzymuje uszeregowane wyniki z atrybucją źródeł i korzysta z kontekstu bez ładowania całych plików. Serwer MCP jest cienką nakładką na silnik wyszukiwania.
Local-first oznacza zerowe koszty API i pełną prywatność. Cały stos działa na jednej maszynie: SQLite do przechowywania danych, Model2Vec do embeddingów (embeddings), FTS5 do wyszukiwania po słowach kluczowych, sqlite-vec do wektorowego KNN. Bez usług chmurowych, bez wywołań API, bez zależności od sieci. Osobiste notatki nigdy nie opuszczają maszyny. Pełne ponowne osadzenie 49 746 chunków kosztowałoby około 0,30 USD według cen OpenAI API, ale rzeczywistymi kosztami są opóźnienia, ekspozycja prywatności i zależność od sieci w systemie, który powinien działać offline.4
Indeksowanie przyrostowe utrzymuje aktualność systemu w mniej niż 10 sekund. Porównanie czasu modyfikacji pliku wykrywa zmiany. Tylko zmodyfikowane pliki są ponownie dzielone na chunki (chunking) i ponownie osadzane. Pełne ponowne indeksowanie zajmuje około czterech minut na sprzęcie Apple z serii M. Aktualizacje przyrostowe po typowych zmianach z danego dnia uruchamiają się w mniej niż dziesięć sekund. System pozostaje aktualny bez ręcznej interwencji.
Architektura skaluje się od 200 do ponad 20 000 notatek. Ten sam trójwarstwowy projekt (pobieranie, wyszukiwanie, integracja) działa przy dowolnym rozmiarze vaulta. Przy małym vaulcie można zacząć od wyszukiwania wyłącznie BM25. Wyszukiwanie wektorowe warto dodać, gdy kolizje słów kluczowych staną się problemem. Fuzję RRF warto dodać wtedy, gdy potrzebne są zarówno dopasowania dokładne, jak i semantyczne. Każda warstwa jest niezależnie użyteczna i niezależnie usuwalna.
Jak korzystać z tego przewodnika
Ten przewodnik obejmuje kompletny system. Punkt startowy zależy od obecnej sytuacji:
| Sytuacja | Proszę zacząć tutaj | Następnie warto przejrzeć |
|---|---|---|
| Początek pracy z Obsidian + AI | Dlaczego Obsidian jako infrastruktura AI, Szybki start | Architektura vaulta, Architektura serwera MCP |
| Istniejący vault, potrzebny dostęp AI | Architektura serwera MCP, Integracja Claude Code | Modele embeddingów, Wyszukiwanie pełnotekstowe |
| Budowa systemu wyszukiwania | Kompletny pipeline wyszukiwania, Reciprocal Rank Fusion | Dostrajanie wydajności, Rozwiązywanie problemów |
| Kontekst zespołowy lub firmowy | Ramy decyzyjne, Wzorce grafu wiedzy | Przepisy dla workflow deweloperskiego, Przewodnik migracji |
Sekcje oznaczone jako Contract zawierają szczegóły implementacyjne, bloki konfiguracji i tryby awarii. Sekcje oznaczone jako Narrative koncentrują się na koncepcjach, decyzjach architektonicznych i uzasadnieniu wyborów projektowych. Sekcje oznaczone jako Recipe podają workflow krok po kroku.
Dlaczego Obsidian jako infrastruktura AI
Teza tego przewodnika brzmi: vaulty Obsidian są najlepszym podłożem dla osobistych baz wiedzy AI, ponieważ są local-first, plaintext, mają strukturę grafu, a użytkownik kontroluje każdą warstwę stosu.
Co Obsidian daje AI, czego nie dają alternatywy
Pliki markdown plaintext. Każda notatka jest plikiem .md w systemie plików. Bez własnościowego formatu, bez eksportu bazy danych, bez wymaganego API do odczytania treści. Każde narzędzie odczytujące pliki może odczytać vault. grep, ripgrep, pathlib z Python, SQLite FTS5 — wszystkie działają bezpośrednio na plikach źródłowych. Przy budowie systemu wyszukiwania indeksowane są pliki, a nie odpowiedzi API. Indeks jest zawsze spójny ze źródłem, ponieważ źródłem jest system plików.
Architektura local-first. Vault znajduje się na maszynie użytkownika. Bez serwera, bez zależności od synchronizacji w chmurze, bez limitów szybkości API, bez warunków korzystania z usługi określających, jak można przetwarzać własne treści. Notatki można osadzać, indeksować, dzielić na chunki i przeszukiwać bez żadnej usługi zewnętrznej. Ma to znaczenie dla infrastruktury AI, ponieważ pipeline wyszukiwania działa tak szybko, jak pozwala dysk, a nie tak szybko, jak odpowiada endpoint API. Ma to również znaczenie dla prywatności: osobiste notatki zawierające dane uwierzytelniające, dane zdrowotne, informacje finansowe i prywatne refleksje nigdy nie opuszczają maszyny.
Struktura grafu dzięki wiki-link. Składnia [[wiki-link]] w Obsidian tworzy skierowany graf pomiędzy notatkami. Notatka o implementacji OAuth linkuje do notatek o rotacji tokenów, zarządzaniu sesją i bezpieczeństwie API. Struktura grafu koduje relacje między pojęciami dobrane przez człowieka. Embeddingi wektorowe wychwytują podobieństwo semantyczne, ale wiki-link przechwytują intencjonalne połączenia utworzone przez autora podczas myślenia o temacie. Graf jest sygnałem, którego embeddingi nie potrafią odtworzyć.
Ekosystem pluginów. Obsidian ma ponad 2 500 pluginów społecznościowych (stan na marzec 2026, wzrost z ponad 1 800 w połowie 2025 roku). Dataview odpytuje vault jak bazę danych. Templater generuje notatki z szablonów z logiką JavaScript. Integracja Git synchronizuje vault z repozytorium. Linter wymusza spójność formatowania. Plugin rdzeniowy Bases (wprowadzony w v1.9.10) dodaje widoki podobne do baz danych — tabele, galerie, kalendarze i tablice kanban — nad plikami vaulta, używając właściwości frontmatter jako pól i zapisując je jako pliki .base.15 Te pluginy dodają strukturę do vaulta bez zmiany bazowego formatu plaintext. System wyszukiwania indeksuje wynik działania tych pluginów, a nie same pluginy.
Ponad 5 milionów użytkowników. Obsidian ma dużą, aktywną społeczność tworzącą szablony, workflow, pluginy i dokumentację. Gdy pojawia się problem z organizacją vaulta lub konfiguracją pluginu, ktoś prawdopodobnie już udokumentował rozwiązanie. Społeczność tworzy także narzędzia wokół Obsidian: serwery MCP, skrypty indeksujące, pipeline publikacji i wrappery API.
Czego nie daje sam system plików
Katalog plików markdown ma zaletę plaintext, ale brakuje mu trzech rzeczy, które dodaje Obsidian:
-
Linki dwukierunkowe. Obsidian automatycznie śledzi backlinki. Gdy link prowadzi z Notatki A do Notatki B, Notatka B pokazuje, że Notatka A się do niej odwołuje. Panel grafu wizualizuje klastry połączeń. Ta dwukierunkowa świadomość jest metadanymi, których surowy system plików nie zapewnia.
-
Podgląd na żywo z renderowaniem pluginów. Zapytania Dataview, diagramy Mermaid i bloki callout renderują się w czasie rzeczywistym. Doświadczenie pisania jest bogatsze niż w edytorze tekstu, a format przechowywania pozostaje plaintext. Pisanie i organizacja odbywają się w rozbudowanym środowisku; system wyszukiwania indeksuje surowy markdown.
-
Infrastruktura społecznościowa. Wyszukiwanie pluginów, marketplace motywów, usługa synchronizacji (opcjonalna), usługa publikacji (opcjonalna) i ekosystem dokumentacji. Każdą pojedynczą funkcję można odtworzyć samodzielnymi narzędziami, ale Obsidian łączy je w spójny workflow.
Czego Obsidian NIE robi (i co należy zbudować)
Obsidian nie zawiera infrastruktury wyszukiwania. Ma podstawowe wyszukiwanie (pełnotekstowe, po nazwie pliku, po tagu), ale nie ma pipeline’u embeddingów, wyszukiwania wektorowego, rankingu fuzyjnego, serwera MCP, filtrowania danych uwierzytelniających, strategii chunkingu ani hooków integracyjnych dla zewnętrznych narzędzi AI. Ten przewodnik opisuje infrastrukturę budowaną na Obsidian. Vault jest podłożem. Pipeline wyszukiwania, serwer MCP i hooki integracyjne są infrastrukturą.
Opisana tutaj architektura jest markdown-first, a nie wyłącznie Obsidian. Jeśli używane są Logseq, Foam, Dendron albo zwykły katalog plików markdown, pipeline wyszukiwania działa identycznie. Chunker odczytuje pliki .md. Embedder przetwarza ciągi tekstowe. Indexer zapisuje dane do SQLite. Żaden z tych komponentów nie zależy od funkcji specyficznych dla Obsidian. Wkładem Obsidian jest środowisko pisania i organizacji, które wytwarza pliki markdown indeksowane przez retriever.
Szybki start: pierwszy magazyn połączony z AI
Ta sekcja pozwala w 5 minut połączyć magazyn z narzędziem AI. Należy zainstalować Obsidian, utworzyć magazyn, zainstalować serwer MCP i uruchomić pierwsze zapytanie. Szybki start wykorzystuje społecznościowy serwer MCP, aby od razu uzyskać wyniki. Późniejsze sekcje omawiają budowanie niestandardowego pipeline’u wyszukiwania do zastosowań produkcyjnych.
Wymagania wstępne
- macOS, Linux lub Windows
- Node.js 18+ (dla serwera MCP)
- Obsidian 1.12+ (dla integracji CLI; wcześniejsze wersje działają w konfiguracjach wyłącznie z MCP)
- Claude Code, Codex CLI lub Cursor
Krok 1: utworzenie magazynu
Należy pobrać Obsidian z obsidian.md i utworzyć nowy magazyn. Proszę wybrać lokalizację, którą łatwo będzie zapamiętać — serwer MCP wymaga ścieżki bezwzględnej.
# Example vault location
~/Documents/knowledge-base/
Warto dodać kilka notatek, aby mechanizm wyszukiwania miał z czym pracować. Nawet 10-20 notatek wystarczy, aby zobaczyć wyniki. Każda notatka powinna być plikiem .md z sensownym tytułem i co najmniej jednym akapitem treści.
Krok 2: instalacja serwera MCP
Kilka społecznościowych serwerów MCP zapewnia natychmiastowy dostęp do magazynu. Ekosystem znacząco rozwinął się w latach 2025-2026. Do ważnych niedawnych aktualizacji należy MCPVault v0.11.0 (marzec 2026), który dodał list_all_tags do skanowania frontmatter i hashtagów wraz z licznikami, ulepszył obsługę folderów z kropkami w nazwach oraz dodał wsparcie dla plików .base i .canvas.13 Pakiet został też przemianowany w npm na @bitbonsai/mcpvault.
Zmiana z kwietnia 2026 — Obsidian CLI jako preferowany most: Obsidian 1.12.0 wprowadził pełnoprawny CLI, a publiczny instalator 1.12.7 (23 marca 2026) zawierał samodzielny plik binarny, TUI oraz ulepszenia pliku socket, które ułatwiły instalację i uruchamianie workflowów terminalowych.16 Narzędzia społecznościowe aktywnie migrują z pluginu Local REST API (który zasilał
mcp-obsidian) do integracji opartej na CLI, ponieważ jest szybsza i stabilniejsza. RepozytoriumMarkusPfundstein/mcp-obsidiannie miało commitów od czerwca 2025 i nigdy nie miało oznaczonych wydań — należy traktować je jako projekt w trybie utrzymania i preferować serwery oparte na CLI albo nowsze alternatywy społecznościowe wymienione poniżej.20 Zalecaną konfigurację opisuje sekcja „Obsidian CLI dla workflowów AI” w dalszej części tego przewodnika.
| Serwer | Autor | Transport | Wymaga pluginu | Kluczowa funkcja |
|---|---|---|---|---|
| obsidian-mcp-server | StevenStavrakis | STDIO | Nie | Lekki, oparty na plikach |
| mcp-obsidian | MarkusPfundstein | STDIO | Local REST API | Pełny CRUD magazynu przez REST — tryb utrzymania, brak commitów od czerwca 202520 |
| obsidian-mcp-tools | jacksteamdev | STDIO | Tak (plugin) | Wyszukiwanie semantyczne + Templater |
| obsidian-claude-code-mcp | iansinnott | WebSocket | Tak (plugin) | Automatyczne wykrywanie dla Claude Code |
| obsidian-mcp-server | cyanheads | STDIO | Local REST API | Tagi, zarządzanie frontmatter |
| Hybrid Search MCP | społeczność | STDIO | Nie | Serwer MCP z BM25 + wyszukiwaniem semantycznym + CLI. Nowy i aktywnie utrzymywany według stanu na kwiecień 2026. |
W szybkim starcie najprostszą opcją jest serwer oparty na plikach, który odczytuje pliki .md bezpośrednio:
npm install -g obsidian-mcp-server
Krok 3: konfiguracja narzędzia AI
Claude Code — należy dodać do ~/.claude/settings.json:
{
"mcpServers": {
"obsidian": {
"command": "obsidian-mcp-server",
"args": ["--vault", "/absolute/path/to/your/vault"]
}
}
}
Codex CLI — należy dodać do .codex/config.toml:
[mcp_servers.obsidian]
command = "obsidian-mcp-server"
args = ["--vault", "/absolute/path/to/your/vault"]
Cursor — należy dodać do .cursor/mcp.json:
{
"mcpServers": {
"obsidian": {
"command": "obsidian-mcp-server",
"args": ["--vault", "/absolute/path/to/your/vault"]
}
}
}
Krok 4: uruchomienie pierwszego zapytania
Należy otworzyć narzędzie AI i zadać pytanie, na które mogą odpowiedzieć notatki z magazynu:
Search my Obsidian vault for notes about [topic you wrote about]
Narzędzie AI wywołuje serwer MCP, który przeszukuje magazyn i zwraca pasujące treści. Powinny pojawić się wyniki ze ścieżkami plików i odpowiednimi fragmentami.
Co właśnie zostało zbudowane
Lokalna baza wiedzy została połączona z narzędziem AI przez standardowy protokół. Serwer MCP odczytuje pliki magazynu, wykonuje podstawowe wyszukiwanie i zwraca wyniki. To minimalna wersja działającego rozwiązania.
Czego ten szybki start NIE zapewnia: - Hybrid retrieval (BM25 + wyszukiwanie wektorowe + RRF fusion) - Wyszukiwania semantycznego opartego na embeddings - Filtrowania poświadczeń - Indeksowania przyrostowego - Automatycznego wstrzykiwania kontekstu opartego na hookach
Pozostała część tego przewodnika omawia budowanie każdej z tych możliwości. Szybki start potwierdza koncepcję. Pełny pipeline zapewnia wyszukiwanie jakości produkcyjnej.
Obsidian CLI dla workflowów AI
Obsidian 1.12 (luty 2026) wprowadził wbudowany interfejs wiersza poleceń, który otwiera nową powierzchnię integracji dla workflowów AI.16 CLI działa jak zdalne sterowanie GUI Obsidian — Obsidian musi być uruchomiony (albo uruchomi się automatycznie przy pierwszym poleceniu). Należy włączyć go w Settings > General > Command line interface.
Dlaczego CLI ma znaczenie dla infrastruktury AI
CLI zapewnia programistyczny dostęp do natywnych operacji Obsidian, które wcześniej wymagały GUI lub pluginów API. Dla workflowów AI kluczowe są następujące możliwości:
- Wyszukiwanie ze skryptów i hooków.
obsidian search "query"orazobsidian search:context "query"uruchamiają wyszukiwanie w magazynie z dowolnego skryptu shell, hooka lub pipeline’u automatyzacji. Wariantsearch:contextzwraca pasujące wiersze wraz z otaczającym kontekstem, co przydaje się przy przekazywaniu wyników do promptów AI. - Automatyzacja notatek dziennych.
obsidian dailyotwiera lub tworzy dzisiejszą notatkę dzienną. W połączeniu ze skryptami shell umożliwia to zautomatyzowane workflowy codziennych briefingów — hook może dopisywać do notatki dziennej podsumowania wygenerowane przez AI. - Tworzenie notatek na podstawie szablonów.
obsidian template listiobsidian template creategenerują notatki z szablonów Templater lub szablonów podstawowych, dzięki czemu agenci AI mogą tworzyć uporządkowane wpisy w magazynie bez bezpośredniego zapisywania plików markdown. - Zarządzanie właściwościami.
obsidian property setiobsidian property getodczytują i zapisują właściwości frontmatter, umożliwiając aktualizacje metadanych ze skryptów bez parsowania YAML. - Kontrola pluginów.
obsidian plugin enable/disable/listzarządza pluginami programistycznie, co jest przydatne przy przełączaniu pluginów indeksujących podczas operacji wsadowych. - Zarządzanie zadaniami.
obsidian task list/add/completezapewnia uporządkowany dostęp do zadań, przydatny dla agentów AI zarządzających elementami pracy w magazynie.
CLI vs MCP w dostępie AI
Serwery CLI i MCP pełnią różne role i wzajemnie się uzupełniają, zamiast konkurować:
| Aspekt | Obsidian CLI | Serwer MCP |
|---|---|---|
| Wywołujący | Skrypty shell, hooki, zadania cron | Agenci AI (Claude Code, Codex, Cursor) |
| Protokół | Proces POSIX (stdin/stdout/stderr) | MCP (JSON-RPC przez STDIO lub HTTP) |
| Mocna strona | Natywne operacje Obsidian (szablony, pluginy, właściwości) | Niestandardowe wyszukiwanie (embeddings, BM25, RRF fusion) |
| Ograniczenie | Brak wyszukiwania wektorowego, brak pipeline’u embeddings | Brak dostępu do wewnętrznych operacji Obsidian |
| Najlepsze zastosowanie | Skrypty automatyzacji, pipeline’y przyjmowania treści, działania hooków | Zapytania agentów AI w czasie rzeczywistym podczas sesji |
Rekomendacja: Warto używać CLI do automatyzacji przyjmowania treści (tworzenia notatek, zarządzania właściwościami, uruchamiania natywnego wyszukiwania Obsidian), a MCP do wyszukiwania (hybrid search z embeddings). Hook PreToolUse może wywołać obsidian search:context jako szybką kontrolę wstępną przed przejściem do pełnego retrievera MCP dla wyników rankingowych.
Przykład: hook przyjmowania treści oparty na CLI
#!/bin/bash
# Hook: append today's signals to daily note via CLI
DATE=$(date +%Y-%m-%d)
SUMMARY="$1"
obsidian daily # ensure daily note exists
obsidian file append "Daily Notes/${DATE}.md" "## AI Summary\n${SUMMARY}"
Wtyczki agentów w Obsidian
Rosnąca kategoria wtyczek Obsidian osadza agentów AI do kodowania bezpośrednio w interfejsie skarbca (vault), stanowiąc alternatywę dla zewnętrznej konfiguracji serwera MCP. Te wtyczki uruchamiają agenta AI w pasku bocznym Obsidian, zamiast łączyć się z narzędzia zewnętrznego.
Claudian
Claudian osadza Claude Code jako współpracownika AI w skarbcu. Katalog skarbca staje się katalogiem roboczym Claude, co daje pełne możliwości agentowe: odczyt i zapis plików, wyszukiwanie, polecenia bash oraz wieloetapowe przepływy pracy.17
Kluczowe funkcje dla infrastruktury AI:
- Prompty świadome kontekstu. Automatycznie dołącza aktywną notatkę, obsługuje wzmianki o plikach @notename, wykluczanie na podstawie tagów oraz zaznaczenie w edytorze jako kontekst.
- Obsługa obrazu. Analiza obrazów przez przeciągnięcie i upuszczenie, wklejenie lub ścieżkę pliku — przydatna do przetwarzania zrzutów ekranu i diagramów zapisanych w skarbcu.
- Polecenia slash. Tworzenie wielokrotnego użytku szablonów promptów uruchamianych przez /command, co umożliwia standaryzację operacji na skarbcu.
- Tryby uprawnień. Tryby YOLO (automatyczne zatwierdzanie), Safe (zatwierdzanie każdej akcji) i Plan (tylko planowanie), z blokadą bezpieczeństwa oraz ograniczeniem do skarbca.
Agent Client
Agent Client wprowadza Claude Code, Codex CLI i Gemini CLI do ujednoliconego paska bocznego Obsidian za pośrednictwem Agent Client Protocol (ACP).18
Kluczowe funkcje:
- Przełączanie między wieloma agentami. Można rozmawiać z Claude Code, Codex lub Gemini CLI z tego samego panelu, przełączając agentów w zależności od potrzeb.
- Wzmianki o notatkach. Użycie @notename pozwala uwzględnić treść notatki w promptach, podobnie jak w Claudian, ale niezależnie od agenta.
- Wykonywanie poleceń shell. Polecenia terminala można wykonywać bezpośrednio w czacie — skrypty build, polecenia git lub dowolne operacje terminalowe bez opuszczania rozmowy.
- Zatwierdzanie działań. Szczegółowa kontrola nad odczytem plików, edycjami i wykonywaniem poleceń.
Kiedy używać wtyczek agentów, a kiedy zewnętrznego MCP
| Scenariusz | Wtyczka agenta | Zewnętrzny MCP |
|---|---|---|
| Pisanie i edytowanie notatek w skarbcu z pomocą AI | Lepsze — agent widzi kontekst edytora | Działa, ale bez świadomości edytora |
| Tworzenie kodu w wielu repozytoriach | Ograniczone — zakres skarbca | Lepsze — zakres projektu z pełnym systemem plików |
| Retrieval z dużego, zindeksowanego korpusu | Tylko podstawowe wyszukiwanie | Pełny pipeline hybrid retrieval |
| Szybkie pytania i odpowiedzi dotyczące skarbca podczas robienia notatek | Idealne — bez przełączania kontekstu | Wymaga przełączenia do terminala |
Rekomendacja: Wtyczek agentów warto używać w przepływach pracy skupionych na skarbcu: pisaniu, porządkowaniu i streszczaniu notatek. Zewnętrzne serwery MCP sprawdzają się lepiej w przepływach deweloperskich, w których agent AI potrzebuje pełnego pipeline’u retrieval oraz dostępu do baz kodu poza skarbcem. Oba podejścia mogą współistnieć — Claudian może działać wewnątrz Obsidian do pracy z notatkami, a Claude Code z MCP zewnętrznie do developmentu.
Framework decyzyjny: Obsidian kontra alternatywy
Nie każdy przypadek użycia wymaga Obsidian. Ta sekcja pokazuje, kiedy Obsidian jest właściwą podstawą, kiedy jest rozwiązaniem nadmiarowym, a kiedy lepiej sprawdzi się coś innego.
Drzewo decyzyjne
START: What is your primary content type?
│
├─ Structured data (tables, records, schemas)
│ → Use a database. SQLite, PostgreSQL, or a spreadsheet.
│ → Obsidian is for prose, not tabular data.
│
├─ Ephemeral context (current project, temporary notes)
│ → Use CLAUDE.md / AGENTS.md in the project repo.
│ → These travel with the code and reset per project.
│
├─ Team wiki (shared documentation, onboarding)
│ → Evaluate Notion, Confluence, or a shared git repo.
│ → Obsidian vaults are personal-first. Team sync is possible
│ but not native.
│
└─ Growing personal knowledge corpus
│
├─ < 50 notes
│ → A folder of markdown files + grep is sufficient.
│ → Obsidian adds value mainly through the link graph,
│ which needs density to be useful.
│
├─ 50 - 500 notes
│ → Obsidian adds value. Wiki-links create a navigable graph.
│ → BM25-only search (FTS5) is sufficient at this scale.
│ → Skip vector search and RRF until keyword collisions appear.
│
├─ 500 - 5,000 notes
│ → Full hybrid retrieval becomes valuable. Keyword collisions
│ increase. Semantic search catches queries that BM25 misses.
│ → Add vector search + RRF fusion at this scale.
│
└─ 5,000+ notes
→ Full pipeline is essential. BM25-only returns too much noise.
→ Credential filtering becomes critical (more notes = more
accidentally pasted secrets).
→ Incremental indexing matters (full reindex takes minutes).
→ MCP integration pays dividends on every AI interaction.
Macierz porównawcza
| Kryterium | Obsidian | Notion | Apple Notes | Zwykły system plików | CLAUDE.md |
|---|---|---|---|---|---|
| Local-first | Tak | Nie (chmura) | Częściowo (iCloud) | Tak | Tak |
| Plaintext | Tak (markdown) | Nie (bloki) | Nie (format własnościowy) | Tak | Tak |
| Struktura grafu | Tak (wiki-links) | Częściowo (wzmianki) | Nie | Nie | Nie |
| Możliwość indeksowania przez AI | Bezpośredni dostęp do plików | Wymagany API | Wymagany eksport | Bezpośredni dostęp do plików | Już w kontekście |
| Ekosystem wtyczek | Ponad 2 500 wtyczek | Integracje | Brak | N/A | N/A |
| Praca offline | Pełna | Buforowane tylko do odczytu | Częściowa | Pełna | Pełna |
| Skalowanie do 10K+ notatek | Tak | Tak (z API) | Pogarsza się | Tak | Nie (pojedynczy plik) |
| Koszt | Bezpłatny (rdzeń) | Od 10 USD/mies. | Bezpłatny | Bezpłatny | Bezpłatny |
Kiedy Obsidian jest rozwiązaniem nadmiarowym
- Kontekst jednego projektu. Jeśli AI potrzebuje tylko kontekstu bieżącej bazy kodu, należy umieścić go w
CLAUDE.md,AGENTS.mdalbo dokumentacji na poziomie projektu. Te pliki podróżują razem z repozytorium i są ładowane automatycznie. - Dane strukturalne. Jeśli treść ma postać tabel, rekordów lub schematów, lepiej użyć bazy danych. Notatki Obsidian są przede wszystkim prozą. Dataview potrafi odpytywać pola frontmatter, ale prawdziwa baza danych lepiej obsługuje zapytania strukturalne.
- Tymczasowy research. Jeśli notatki zostaną usunięte po zakończeniu projektu, prostszy będzie katalog roboczy z plikami markdown. Nie warto budować infrastruktury retrieval dla treści efemerycznych.
Kiedy Obsidian jest właściwym wyborem
- Gromadzenie wiedzy przez miesiące lub lata. Wartość rośnie wraz z korpusem. Skarbiec z 200 notatkami odpytywany codziennie przez sześć miesięcy daje więcej wartości niż skarbiec z 5 000 notatkami odpytany raz.
- Wiele domen w jednym korpusie. Skarbiec zawierający notatki o programowaniu, architekturze, bezpieczeństwie, projektowaniu i projektach osobistych korzysta z retrieval międzydomenowego, którego projektowy
CLAUDE.mdnie zapewni. - Treści wrażliwe prywatnościowo. Local-first oznacza, że pipeline retrieval nigdy nie wysyła treści do usług zewnętrznych. Skarbiec zawiera wszystko, co zostanie w nim umieszczone, także treści, których nie przesłano by do usługi chmurowej.
Model mentalny: trzy warstwy
System ma trzy warstwy, które działają niezależnie, ale po połączeniu wzajemnie wzmacniają swoją wartość. Każda warstwa odpowiada za inny aspekt i ma inny tryb awarii.
┌─────────────────────────────────────────────────────┐
│ INTEGRATION LAYER │
│ MCP servers, hooks, skills, context injection │
│ Concern: delivering context to AI tools │
│ Failure: wrong context, too much context, stale │
└──────────────────────┬──────────────────────────────┘
│ query + ranked results
┌──────────────────────┴──────────────────────────────┐
│ RETRIEVAL LAYER │
│ BM25, vector KNN, RRF fusion, token budget │
│ Concern: finding the right content for any query │
│ Failure: wrong ranking, missed results, slow queries │
└──────────────────────┬──────────────────────────────┘
│ chunked, embedded, indexed
┌──────────────────────┴──────────────────────────────┐
│ INTAKE LAYER │
│ Note creation, signal triage, vault organization │
│ Concern: what enters the vault and how it's stored │
│ Failure: noise, duplicates, missing structure │
└─────────────────────────────────────────────────────┘
Intake określa, co trafia do skarbca. Bez kuracji skarbiec gromadzi szum: zrzuty ekranu tweetów, skopiowane artykuły bez adnotacji, niedokończone myśli bez kontekstu. Warstwa intake odpowiada za kontrolę jakości w punkcie wejścia. Pipeline scoringowy, konwencja tagowania albo ręczny proces przeglądu — dowolny mechanizm, który zapewnia, że skarbiec zawiera treści warte późniejszego wyszukania.
Retrieval sprawia, że skarbiec można odpytywać. To silnik: dzielenie notatek na jednostki wyszukiwania przez chunking, osadzanie chunków w przestrzeni wektorowej jako embeddings, indeksowanie pod kątem wyszukiwania słów kluczowych i semantycznego oraz łączenie wyników za pomocą RRF. Warstwa retrieval przekształca katalog plików w odpytywalną bazę wiedzy. Bez tej warstwy po skarbcu można poruszać się przez ręczne przeglądanie i podstawowe wyszukiwanie, ale nie jest on programowo dostępny dla narzędzi AI.
Integration łączy warstwę retrieval z narzędziami AI. Serwer MCP udostępnia retrieval jako wywoływalne narzędzie. Hooki automatycznie wstrzykują kontekst. Skills zapisują nową wiedzę z powrotem w skarbcu. Warstwa integration jest interfejsem między bazą wiedzy a agentami AI, które z niej korzystają.
Warstwy są celowo odsprzęgnięte. Pipeline scoringowy intake nie wie nic o embeddings. Retriever nie wie nic o regułach routingu sygnałów. Serwer MCP nie wie nic o tym, jak powstały notatki. To odsprzęgnięcie oznacza, że każdą warstwę można ulepszać niezależnie. Można wymienić model embeddingów bez zmiany pipeline’u intake. Dodać nową funkcję MCP bez modyfikowania retrievera. Zmienić heurystyki scoringu sygnałów bez dotykania indeksu.
Architektura magazynu na potrzeby AI
Magazyn zoptymalizowany pod kątem wyszukiwania przez AI rządzi się innymi konwencjami niż magazyn zoptymalizowany do osobistego przeglądania. Ta sekcja omawia strukturę folderów, schemat notatek, konwencje frontmatter oraz konkretne wzorce, które poprawiają jakość wyszukiwania.
Struktura folderów
W przypadku folderów najwyższego poziomu warto używać numerowanych prefiksów, aby utworzyć przewidywalną hierarchię organizacyjną. Numery nie oznaczają priorytetu — grupują powiązane domeny i sprawiają, że strukturę łatwiej przeskanować wzrokiem.
vault/
├── 00-inbox/ # Unsorted captures, pending triage
├── 01-projects/ # Active project notes
├── 02-areas/ # Ongoing areas of responsibility
├── 03-resources/ # Reference material by topic
│ ├── programming/
│ ├── security/
│ ├── ai-engineering/
│ ├── design/
│ └── devops/
├── 04-archive/ # Completed projects, old references
├── 05-signals/ # Scored signal intake
│ ├── ai-tooling/
│ ├── security/
│ ├── systems/
│ └── ...12 domain folders
├── 06-daily/ # Daily notes (if used)
├── 07-templates/ # Note templates (excluded from index)
├── 08-attachments/ # Images, PDFs (excluded from index)
├── .obsidian/ # Obsidian config (excluded from index)
└── .indexignore # Paths to exclude from retrieval index
Foldery, które należy indeksować: Wszystko, co zawiera prozę w markdown — projekty, obszary, zasoby, sygnały, notatki dzienne.
Foldery, które należy wykluczyć z indeksowania: Szablony (zawierają zmienne zastępcze, a nie treść), załączniki (pliki binarne), konfigurację Obsidian oraz każdy folder zawierający treści poufne, których nie należy umieszczać w indeksie wyszukiwania.
Plik .indexignore
W katalogu głównym magazynu należy utworzyć plik .indexignore, aby jawnie wykluczyć ścieżki z indeksu wyszukiwania. Składnia odpowiada .gitignore:
# Obsidian internal
.obsidian/
# Templates contain placeholders, not content
07-templates/
# Binary attachments
08-attachments/
# Personal health/medical notes
02-areas/health/
# Financial records
02-areas/finance/personal/
# Career documents (resumes, salary data)
02-areas/career/private/
Indekser odczytuje ten plik przed skanowaniem i całkowicie pomija pasujące ścieżki. Pliki w wykluczonych ścieżkach nigdy nie są dzielone na chunks, nie otrzymują embeddings i nigdy nie pojawiają się w wynikach wyszukiwania.
Schemat notatek
Każda notatka powinna mieć frontmatter YAML. Retriever używa pól frontmatter do filtrowania i wzbogacania kontekstu:
---
title: "OAuth Token Rotation Patterns"
type: note # note | signal | project | moc | daily
domain: security # primary domain for routing
tags:
- authentication
- oauth
- token-management
created: 2026-01-15
updated: 2026-02-28
source: "" # URL if captured from external source
status: active # active | archived | draft
---
Pola wymagane do wyszukiwania:
title— Używane w wyświetlaniu wyników wyszukiwania oraz w kontekście nagłówka dla BM25type— Umożliwia zapytania filtrowane według typu („pokaż tylko MOC” albo „tylko sygnały”)tags— Indeksowane w kontekście nagłówka FTS5 z wagą 0,3, zapewniając dopasowania słów kluczowych nawet wtedy, gdy treść używa innej terminologii
Pola opcjonalne, ale wartościowe:
domain— Umożliwia zapytania ograniczone do domeny („wyszukaj tylko notatki o bezpieczeństwie”)source— Atrybucja przechwyconych treści; retriever może uwzględniać źródłowe URL-e w wynikachstatus— Pozwala wykluczać z aktywnego wyszukiwania notatki zarchiwizowane lub robocze
Konwencje chunking
Retriever dzieli treść na chunks na granicach nagłówków H2 (##). Oznacza to, że struktura notatki bezpośrednio wpływa na szczegółowość wyszukiwania:
Dobre dla wyszukiwania:
## Token Rotation Strategy
The rotation interval depends on the threat model...
## Implementation with refresh_token
The OAuth 2.0 refresh token flow requires...
## Error Handling: Expired Tokens
When a token expires mid-request...
Trzy sekcje H2 tworzą trzy niezależnie przeszukiwalne chunks. Każdy chunk ma wystarczający kontekst, aby embedding uchwycił jego znaczenie. Zapytanie o „obsługę wygasłych tokenów” dopasowuje konkretnie trzeci chunk.
Słabe dla wyszukiwania:
# OAuth Notes
Token rotation depends on threat model. The OAuth 2.0 refresh
token flow requires storing the refresh token securely. When a
token expires mid-request, the client should retry after refresh.
The rotation interval is typically 15-30 minutes for access tokens
and 7-30 days for refresh tokens...
Jedna długa sekcja bez nagłówków H2 tworzy jeden duży chunk. Embedding uśrednia wszystkie tematy w sekcji. Zapytanie o dowolny podtemat dopasowuje całą notatkę w takim samym stopniu.
Praktyczna zasada: Jeśli sekcja obejmuje więcej niż jedno pojęcie, należy podzielić ją na podsekcje H2. Chunker zajmie się resztą.
Czego nie umieszczać w notatkach
Treści, które obniżają jakość wyszukiwania:
- Surowe kopiuj-wklej całych artykułów bez adnotacji. Retriever indeksuje słowa kluczowe z oryginalnego artykułu, rozmywając magazyn treściami, których autor nie napisał. Zamiast tego warto dodać podsumowanie, wyodrębnić kluczowe punkty albo podać link do źródłowego URL-a.
- Zrzuty ekranu bez opisu tekstowego. Retriever indeksuje tekst markdown. Obraz bez tekstu alternatywnego lub otaczającego opisu jest niewidoczny zarówno dla BM25, jak i wyszukiwania wektorowego.
- Ciągi danych uwierzytelniających. Klucze API, tokeny, hasła, connection strings. Nawet przy filtrowaniu danych uwierzytelniających najbezpieczniej nigdy nie wklejać sekretów do notatek. Zamiast tego należy odwoływać się do nich nazwą („token Cloudflare API w
~/.env”). - Automatycznie generowane treści bez kuracji. Jeśli narzędzie generuje notatkę (transkrypt spotkania, wyróżnienia z Readwise, import RSS), należy ją przejrzeć i opatrzyć adnotacjami, zanim trafi do stałego magazynu. Nieselekcjonowane automatyczne importy zwiększają objętość, nie dodając wartości możliwej do wyszukania.
Ekosystem wtyczek dla przepływów pracy AI
Wtyczki Obsidian poprawiające jakość sejfu pod kątem wyszukiwania AI dzielą się na trzy kategorie: strukturalne (wymuszają spójność), zapytaniowe (ujawniają metadane) oraz synchronizacyjne (utrzymują sejf w aktualnym stanie).
Niezbędne wtyczki
Dataview. Przeszukuje sejf jak bazę danych, korzystając z pól frontmatter. Można tworzyć dynamiczne indeksy: „wszystkie notatki oznaczone tagiem security, zaktualizowane w ciągu ostatnich 30 dni” albo „wszystkie notatki projektowe ze statusem active”. Dataview nie wspiera bezpośrednio wyszukiwania, ale pomaga identyfikować luki w pokryciu sejfu i znajdować notatki wymagające aktualizacji.
TABLE type, domain, updated
FROM "03-resources"
WHERE status = "active"
SORT updated DESC
LIMIT 20
Templater. Tworzy notatki z szablonów z polami dynamicznymi. Warto zadbać, aby każda nowa notatka zaczynała się od poprawnego frontmatter, używając szablonu, który wstępnie wypełnia pola created, type i domain. Spójny frontmatter usprawnia filtrowanie wyników wyszukiwania.
<%* /* New Resource Note Template */ %>
---
title: "<% tp.file.cursor() %>"
type: note
domain: <% tp.system.suggester(["programming", "security", "ai-engineering", "design", "devops"], ["programming", "security", "ai-engineering", "design", "devops"]) %>
tags: []
created: <% tp.date.now("YYYY-MM-DD") %>
updated: <% tp.date.now("YYYY-MM-DD") %>
source: ""
status: active
---
## Key Points
## Details
## References
Linter. Wymusza reguły formatowania w całym sejfie. Spójna hierarchia nagłówków (H1 dla tytułu, H2 dla sekcji, H3 dla podsekcji) sprawia, że chunker daje przewidywalne wyniki. Reguły Lintera istotne dla wyszukiwania:
- Przyrost nagłówków: wymuszanie kolejnych poziomów nagłówków (bez przeskakiwania z H1 do H3)
- Tytuł YAML: zgodny z nazwą pliku
- Końcowe spacje: usuwanie (zapobiega artefaktom tokenizacji FTS5)
- Kolejne puste wiersze: ograniczenie do 1 (czystsze fragmenty)
Git integration. Kontrola wersji dla sejfu. Pozwala śledzić zmiany w czasie, synchronizować między komputerami i odzyskiwać przypadkowo usunięte treści. Git udostępnia też dane mtime, których indekser używa do przyrostowego wykrywania zmian.
Wtyczki wspierające indeksowanie
Smart Connections. Wtyczka Obsidian zapewniająca semantyczne wyszukiwanie oparte na AI bezpośrednio w Obsidian. Smart Connections v4 domyślnie tworzy lokalne embeddings — po zindeksowaniu sejfu połączenia semantyczne i wyszukiwanie działają całkowicie offline, bez wywołań API.11 v4.5.0 (5 maja 2026) przenosi połączenia w stopce do Smart Connections Core, dzięki czemu każda instalacja może pokazywać powiązane notatki w stopce bez otwierania panelu bocznego. Ostatnie wydania v4 dodały też widoki grafu dla list połączeń, konfigurowalne położenia dokowania, lepsze odzyskiwanie embeddings bloków po przerwanych przebiegach indeksowania oraz „Substrate”, środowisko międzywtyczkowe pozwalające Smart Connections, Smart Chat i Smart Composer współdzielić stan.21 Choć system wyszukiwania z tego przewodnika działa poza Obsidian (jako pipeline Python), Smart Connections przydaje się do odkrywania relacji semantycznych podczas pisania. Oba systemy indeksują te same treści, ale obsługują inne przypadki użycia: Smart Connections służy do odkrywania treści w edytorze, a zewnętrzny retriever do integracji z narzędziami AI przez MCP.
Wtyczki AI-native wydane w kwietniu 2026. Nowa fala wtyczek społecznościowych celuje bezpośrednio w przepływ pracy Claude Code / Codex / Gemini-CLI:
| Wtyczka | Wydana | Co robi |
|---|---|---|
| Cortex | 4 kwietnia | Agent sejfu oparty na Claude Code — traktuje sejf jako przestrzeń roboczą agenta, a nie tylko magazyn notatek |
| VaultSearch | 7 kwietnia | Lokalne-first wyszukiwanie hybrydowe: BM25 + semantyczne + rozmyte (bezpośrednie pokrycie ze stosem wyszukiwania z tego przewodnika) |
| LLM Wiki | 9 kwietnia | Zamienia sejf w prywatnie odpytywalną bazę wiedzy |
| Drift | 11 kwietnia | Przeglądarka diffów w stylu VS Code do edycji Obsidian wspieranej przez AI; pozycjonowana pod przepływy pracy Claude Code |
| EngramQuest | 11 kwietnia | Generuje wyzwania pamięciowe z notatek; zawiera „AI Skills” dla Claude Code / Gemini CLI / Cursor |
| Hybrid Search MCP | marzec (nadal nowe) | Serwer MCP + CLI z BM25 + wyszukiwaniem semantycznym — zbudowany specjalnie dla asystentów AI |
Należy traktować to jako dopiero wyłaniający się obszar — kilka z tych rozwiązań prawdopodobnie połączy się albo zostanie wchłoniętych przez Smart Connections / rdzeń Obsidian w ciągu kilku kolejnych kwartałów. Jeśli wybiera się dziś jedno narzędzie, VaultSearch i Hybrid Search MCP są filozoficznie najbliższe zewnętrznemu retrieverowi opisanemu w tym przewodniku.
Uwaga o Dataview: Dataview (od dawna istniejąca wtyczka zapytań dla Obsidian) ostatnio wydał wersję 0.5.70 w kwietniu 2025 roku i od tego czasu pozostaje zasadniczo nieaktywny. W przypadku nowych prac wbudowana funkcja Bases w Obsidian (1.9+) jest domyślnym następcą i zalecaną ścieżką.
Metadata Menu. Zapewnia strukturalną edycję frontmatter z autouzupełnianiem wartości pól. Ogranicza literówki w polach type, domain i tags. Spójne metadane zwiększają dokładność filtrowania wyników wyszukiwania.
Wtyczki utrudniające indeksowanie
Excalidraw. Przechowuje rysunki jako JSON osadzone w plikach markdown. JSON jest składniowo poprawnym markdown, ale po podziale na fragmenty i utworzeniu embeddings daje bezużyteczne wyniki. Pliki Excalidraw należy wykluczyć z indeksu przez .indexignore albo filtrować według rozszerzenia pliku.
Kanban. Przechowuje stan tablicy jako specjalnie sformatowany markdown. Format jest zaprojektowany pod renderowanie Kanban, a nie wyszukiwanie w prozie. Chunker tworzy fragmenty tytułów kart i metadanych, które słabo nadają się do embeddings. Tablice Kanban należy wykluczyć z indeksu.
Calendar. Tworzy notatki dzienne z minimalną zawartością (często tylko nagłówkiem daty). Puste lub prawie puste notatki tworzą fragmenty niskiej jakości. Jeśli używa się notatek dziennych, należy wpisywać w nich treściwe informacje albo wykluczyć folder notatek dziennych z indeksu.
Konfiguracja wtyczek, która ma znaczenie
File recovery → Enabled. Chroni przed przypadkowym usunięciem notatek. Nie jest bezpośrednio związane z wyszukiwaniem, ale ma krytyczne znaczenie dla bazy wiedzy, na której można polegać.
Strict line breaks → Disabled. Standardowe łamanie wierszy w Markdown (podwójny znak nowego wiersza dla akapitu) daje czystsze fragmenty niż tryb ścisły Obsidian (pojedynczy znak nowego wiersza dla <br>).
Default new file location → Designated folder. Nowe pliki należy kierować do 00-inbox/, aby nieskategoryzowane notatki nie zanieczyszczały folderów domenowych. Inbox jest obszarem przejściowym; po triage pliki przenosi się do folderów domenowych.
Wiki-link format → Shortest path when possible. Krótsze cele linków są łatwiejsze do rozwiązania przez retriever podczas indeksowania struktury linków.
Modele embeddings: wybór i konfiguracja
Model embeddingów przekształca fragmenty tekstu w wektory liczbowe na potrzeby wyszukiwania semantycznego. Wybór modelu decyduje o jakości wyszukiwania, rozmiarze indeksu, szybkości generowania embeddingów i zależnościach uruchomieniowych. W tej sekcji wyjaśniono, dlaczego Model2Vec potion-base-8M jest wyborem domyślnym i kiedy warto wybrać alternatywy.
Dlaczego Model2Vec potion-base-8M
Model: minishlab/potion-base-8M
Parametry: 7,6 miliona
Wymiary: 256
Rozmiar: ~30 MB
Zależności: model2vec (tylko numpy, bez PyTorch)
Inferencja: tylko CPU, statyczne embeddingi słów (bez warstw attention)
Model2Vec destyluje wiedzę transformera zdań do statycznych embeddingów tokenów. Zamiast uruchamiać warstwy attention na wejściu (jak robią to BERT, MiniLM i inne modele transformerowe), Model2Vec tworzy wektory przez ważone uśrednianie wcześniej obliczonych embeddingów tokenów.5 Praktyczny skutek: generowanie embeddingów jest 50-500 razy szybsze niż w modelach opartych na transformerach, ponieważ nie ma obliczeń sekwencyjnych.
Na aktualnej stronie wyników Model2Vec potion-base-8M osiąga około 92% wyniku all-MiniLM-L6-v2 dla wszystkich zadań (51,32 wobec 55,80), pozostając przy tym o rzędy wielkości szybszy.6 Pozostała różnica jakości to kompromis za przewagi szybkości i prostoty. W przypadku krótkich fragmentów markdown (średnio 200-400 słów w typowym vault) różnica jakości jest mniej wyraźna niż przy dłuższych dokumentach, ponieważ oba modele zbiegają się ku podobnym reprezentacjom krótkiego, skoncentrowanego tekstu.
Konfiguracja
# embedder.py
DEFAULT_MODEL = "minishlab/potion-base-8M"
EMBEDDING_DIM = 256
class Model2VecEmbedder:
def __init__(self, model_name=DEFAULT_MODEL):
self._model_name = model_name
self._model = None
def _ensure_model(self):
if self._model is not None:
return
_activate_venv() # Add isolated venv to sys.path
from model2vec import StaticModel
self._model = StaticModel.from_pretrained(self._model_name)
def embed_batch(self, texts):
self._ensure_model()
vecs = self._model.encode(texts)
return [v.tolist() for v in vecs]
Leniwe ładowanie. Model ładuje się przy pierwszym użyciu, a nie podczas importu. Import modułu embeddera nic nie kosztuje, gdy retriever działa w trybie awaryjnym wyłącznie BM25 (np. gdy venv dla embeddingów nie jest zainstalowany).
Izolowane środowisko wirtualne. Model działa w dedykowanym venv (np. ~/.claude/venvs/memory/), aby uniknąć konfliktów zależności z resztą toolchaina. Funkcja _activate_venv() dodaje site-packages z venv do sys.path w czasie działania.
# Create isolated venv
python3 -m venv ~/.claude/venvs/memory
~/.claude/venvs/memory/bin/pip install model2vec
Przetwarzanie wsadowe. Embedder przetwarza teksty w paczkach po 64, aby zamortyzować narzut Model2Vec. Indexer przekazuje fragmenty do embed_batch(), zamiast generować embedding dla każdego fragmentu osobno.
Kiedy wybrać alternatywy
| Model | Wym. | Rozmiar | Szybkość | Jakość (MTEB) | Najlepsze zastosowanie |
|---|---|---|---|---|---|
| potion-base-8M | 256 | 30 MB | 500x | 51,32 | Domyślnie: lokalnie, szybko, bez GPU |
| potion-base-32M | 256 | 120 MB | 400x | 52,83 | Wyższa jakość, nadal statyczny |
| potion-retrieval-32M | 256 | 120 MB | 400x | 35,06 (retrieval) | Statyczny, zoptymalizowany pod retrieval |
| potion-multilingual-128M | 256 | ~500 MB | 300x | — | Wielojęzyczne vaulty (101 języków) |
| all-MiniLM-L6-v2 | 384 | 80 MB | 1x | 55,80 | Wyższa jakość, nadal lokalnie |
| nomic-embed-text-v1.5 | 768 | 270 MB | 0,5x | 62,28 | Najlepsza jakość lokalna |
| text-embedding-3-small | 1536 | API | N/A | 62,30 | Oparty na API, najwyższa jakość |
Warto wybrać potion-base-32M, gdy potrzebna jest lepsza jakość niż potion-base-8M bez wychodzenia poza rodzinę statycznych embeddingów. Model używa większego słownika wydestylowanego z baai/bge-base-en-v1.5, osiągając wynik 52,83 dla wszystkich zadań (około 3% wyżej niż potion-base-8M), przy zachowaniu tego samego 256-wymiarowego wyjścia i zależności wyłącznie od numpy.8 Plik modelu większy 4 razy zwiększa zużycie pamięci, ale szybkość generowania embeddingów pozostaje o rzędy wielkości wyższa niż w modelach transformerowych.
Warto wybrać potion-retrieval-32M, gdy podstawowym przypadkiem użycia jest retrieval (a tym właśnie jest wyszukiwanie w vault). Ten wariant jest dostrajany na bazie potion-base-32M specjalnie pod zadania retrieval, osiągając 35,06 w tabeli benchmarków retrieval Model2Vec wobec 32,67 dla potion-base-32M.8 Kompromis polega na tym, że model jest zoptymalizowany pod retrieval, a nie pod ogólną jakość embeddingów.
Warto wybrać potion-multilingual-128M, gdy vault zawiera notatki w wielu językach. Ten 101-języczny model, wydany w maju 2025 roku, jest najlepiej działającym statycznym modelem embeddingów dla zadań wielojęzycznych: generuje embeddingi dla dowolnego tekstu w dowolnym języku, zachowując tę samą zależność wyłącznie od numpy co inne modele potion.12 Większy plik modelu (~500 MB) jest kompromisem za obsługę międzyjęzykową. Należy go używać, gdy obok treści angielskich występują notatki po japońsku, chińsku, niemiecku lub w innych językach nieangielskich.
Warto wybrać all-MiniLM-L6-v2, gdy jakość wyszukiwania jest ważniejsza niż szybkość i zainstalowany jest PyTorch. Wektory 384-wymiarowe zwiększają rozmiar bazy SQLite o ~50% względem wektorów 256-wymiarowych. Szybkość generowania embeddingów spada z <1 minuty do ~10 minut dla pełnego ponownego indeksowania 15 000 plików na sprzęcie M-series.
Warto wybrać nomic-embed-text-v1.5, gdy potrzebna jest najlepsza możliwa lokalna jakość retrieval i akceptowane jest wolniejsze indeksowanie. Wektory 768-wymiarowe w przybliżeniu potrajają rozmiar bazy danych. Wymaga PyTorch oraz nowoczesnego CPU lub GPU.
Warto wybrać text-embedding-3-small, gdy opóźnienia sieciowe i prywatność są akceptowalnymi kompromisami. API tworzy embeddingi najwyższej jakości, ale wprowadza zależność od chmury, koszt za token (0,02 USD / milion tokenów) i wysyła treści na serwery OpenAI.
Przy potion-base-8M warto pozostać we wszystkich pozostałych przypadkach. Przewaga szybkości jest kluczowa dla iteracyjnego indeksowania (ponowne indeksowanie podczas developmentu), zależność wyłącznie od numpy pozwala uniknąć złożoności instalacji PyTorch, a wektory 256-wymiarowe utrzymują kompaktowy rozmiar bazy danych.
Kwantyzacja i redukcja wymiarowości
Model2Vec v0.5.0+ obsługuje ładowanie modeli ze zmniejszoną precyzją i liczbą wymiarów.8 Przydaje się to przy wdrażaniu na ograniczonym sprzęcie lub zmniejszaniu rozmiaru bazy danych bez zmiany modelu:
from model2vec import StaticModel
# Load with int8 quantization (25% of original size)
model = StaticModel.from_pretrained("minishlab/potion-base-8M", quantize=True)
# Load with reduced dimensions (e.g., 128 instead of 256)
model = StaticModel.from_pretrained("minishlab/potion-base-8M", dimensionality=128)
Modele skwantyzowane zachowują niemal identyczną jakość retrieval przy ułamku zapotrzebowania na pamięć. Redukcja wymiarowości działa jak przycinanie w stylu Matryoshka — pierwsze N wymiarów niesie najwięcej informacji. Zmniejszenie z 256 do 128 wymiarów obniża o połowę rozmiar przechowywania wektorów przy minimalnej utracie jakości w retrieval krótkich tekstów.
Model2Vec v0.8.x aktualizuje mechanizmy tokenizera i utrwalania, wycofuje obsługę Python 3.9 oraz odświeża opublikowane wyniki do nowszych tabel MTEB. Przed aktualizacją produkcyjnego indexera należy przypiąć lub przetestować model2vec, ponieważ aktualizacje biblioteki mogą zmienić ścieżki ładowania modelu nawet wtedy, gdy nazwa modelu embeddingów pozostaje taka sama.10
Fine-tuning embeddingów specyficznych dla vault
Model2Vec v0.4.0+ obsługuje trenowanie niestandardowych modeli klasyfikacyjnych na statycznych embeddingach, v0.7.0 dodaje kwantyzację słownika i konfigurowalne pooling dla destylacji, a v0.8.x refaktoryzuje zachowanie tokenizera i utrwalania.10 Ma to znaczenie w vaultach ze specjalistycznym słownictwem (notatki medyczne, odniesienia prawne, żargon domenowy), gdzie domyślne modele potion mogą nie uchwycić niuansów semantycznych:
from model2vec import StaticModel
from model2vec.train import train_model
# Fine-tune on vault-specific data
model = StaticModel.from_pretrained("minishlab/potion-base-8M")
trained_model = train_model(model, train_texts, train_labels)
trained_model.save_pretrained("./vault-embeddings")
W większości vaultów domyślny potion-base-8M zapewnia wystarczającą jakość retrieval. Fine-tuning ma sens tylko wtedy, gdy retrieval konsekwentnie pomija połączenia specyficzne dla domeny, których model ogólnego przeznaczenia nie potrafi uchwycić.
Śledzenie hash modelu
Indexer przechowuje hash wyprowadzony z nazwy modelu i rozmiaru słownika. Po zmianie modelu embeddingów indexer wykrywa niezgodność przy następnym przebiegu przyrostowym i automatycznie uruchamia pełne ponowne indeksowanie.
def _compute_model_hash(self):
"""Hash model name + vocab size for compatibility tracking."""
key = f"{self._model_name}:{self._model.vocab_size}"
return hashlib.sha256(key.encode()).hexdigest()[:16]
Zapobiega to mieszaniu w tej samej bazie danych wektorów pochodzących z różnych modeli, co dawałoby bezsensowne wyniki cosine similarity.
Tryby awarii
Niepowodzenie pobierania modelu. Pierwsze uruchomienie pobiera model z Hugging Face. Jeśli pobieranie się nie powiedzie (problem z siecią, firmowy firewall), retriever przechodzi w tryb wyłącznie BM25. Po pierwszym pobraniu model jest przechowywany lokalnie w cache.
Niezgodność wymiarów. Jeśli model zostanie zmieniony bez wyczyszczenia bazy danych, zapisane wektory mają inny wymiar niż nowe embeddingi. Indexer wykrywa to za pomocą hash modelu i uruchamia pełne ponowne indeksowanie. Jeśli kontrola hash się nie powiedzie (niestandardowy model bez poprawnego hash), sqlite-vec zgłosi błąd przy zapytaniach KNN z niezgodnymi wymiarami.
Presja pamięci przy dużych vaultach. Generowanie embeddingów dla ponad 50 000 fragmentów w jednej paczce może zużyć znaczną ilość pamięci. Indexer przetwarza dane w paczkach po 64, aby ograniczyć szczytowe zużycie pamięci. Jeśli pamięć nadal stanowi problem, należy zmniejszyć rozmiar paczki.
Wyszukiwanie pełnotekstowe z FTS5
Rozszerzenie FTS5 w SQLite zapewnia wyszukiwanie pełnotekstowe z rankingiem BM25. FTS5 jest komponentem wyszukiwania po słowach kluczowych w potoku wyszukiwania hybrid retrieval. Ta sekcja omawia konfigurację FTS5, sytuacje, w których BM25 sprawdza się najlepiej, oraz jego konkretne tryby awarii.
Tabela wirtualna FTS5
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text,
section,
heading_context,
content=chunks,
content_rowid=id
);
Tryb synchronizacji treści. Parametr content=chunks informuje FTS5, aby odwoływał się bezpośrednio do tabeli chunks, zamiast przechowywać zduplikowaną kopię tekstu. Zmniejsza to wymagania dotyczące pamięci masowej o połowę, ale oznacza, że FTS5 trzeba synchronizować ręcznie, gdy fragmenty są wstawiane, aktualizowane lub usuwane.
Kolumny. Indeksowane są 3 kolumny:
- chunk_text — główna treść każdego fragmentu (waga BM25: 1.0)
- section — tekst nagłówka H2 (waga BM25: 0.5)
- heading_context — tytuł notatki, tagi i metadane (waga BM25: 0.3)
Ranking BM25
BM25 szereguje dokumenty według częstotliwości termów, odwrotnej częstotliwości dokumentów oraz normalizacji długości dokumentu. Funkcja pomocnicza bm25() w FTS5 przyjmuje wagi dla poszczególnych kolumn:
SELECT
c.id, c.file_path, c.section, c.chunk_text,
bm25(chunks_fts, 1.0, 0.5, 0.3) AS score
FROM chunks_fts
JOIN chunks c ON chunks_fts.rowid = c.id
WHERE chunks_fts MATCH ?
ORDER BY score
LIMIT 30;
Wagi kolumn (1.0, 0.5, 0.3) oznaczają, że:
- dopasowanie słowa kluczowego w chunk_text ma największy wpływ na wynik
- dopasowanie w section (nagłówku) ma o połowę mniejszy wpływ
- dopasowanie w heading_context (tytuł, tagi) ma 30% tego wpływu
Te wagi można dostrajać. Jeśli repozytorium Obsidian (vault) ma opisowe nagłówki, które silnie przewidują jakość treści, warto zwiększyć wagę section. Jeśli tagi są kompletne i trafne, warto zwiększyć wagę heading_context.
Kiedy BM25 wygrywa
BM25 świetnie sprawdza się przy zapytaniach zawierających dokładne identyfikatory:
- Nazwy funkcji:
_rrf_fuse,embed_batch,get_stale_files - Flagi CLI:
--incremental,--vault,--model - Klucze konfiguracji:
bm25_weight,max_tokens,batch_size - Komunikaty błędów:
SQLITE_LOCKED,ConnectionRefusedError - Konkretne terminy specjalistyczne:
PostToolUse,PreToolUse,AGENTS.md
Dla takich zapytań BM25 natychmiast znajduje dokładne dopasowanie. Wyszukiwanie wektorowe zwróciłoby treści powiązane semantycznie, ale mogłoby sklasyfikować dokładne dopasowanie niżej niż omówienie koncepcyjne.
Kiedy BM25 zawodzi
BM25 zawodzi przy zapytaniach, które używają innej terminologii niż przechowywana treść:
- Zapytanie: „jak obsługiwać niepowodzenia uwierzytelniania” → Repozytorium zawiera notatki o „odzyskiwaniu po błędach logowania” i „obsłudze wygasania sesji”. BM25 nie dopasowuje wyników, ponieważ słowa kluczowe się różnią.
- Zapytanie: „jaki jest najlepszy sposób zarządzania stanem” → Repozytorium zawiera notatki o „wzorcach Redux store” i „context providers”. BM25 ich nie znajduje, ponieważ „zarządzanie stanem” jest wyrażone przez nazwy konkretnych technologii.
BM25 zawodzi również przy kolizji słów kluczowych na dużą skalę. W repozytorium zawierającym 15 000 plików wyszukiwanie „configuration” dopasowuje setki notatek, ponieważ prawie każda notatka projektowa wspomina o konfiguracji. Wyniki są technicznie poprawne, ale praktycznie bezużyteczne — ranking nie jest w stanie określić, która notatka o „configuration” jest istotna dla bieżącego zapytania.
Tokenizer FTS5
FTS5 domyślnie używa tokenizera unicode61, który obsługuje tekst ASCII i Unicode. W przypadku repozytoriów ze znaczną ilością treści CJK (chińskiej, japońskiej, koreańskiej) warto rozważyć tokenizer trigram:
-- For CJK-heavy vaults
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text, section, heading_context,
content=chunks, content_rowid=id,
tokenize='trigram'
);
Domyślny tokenizer unicode61 dzieli tekst na granicach wyrazów, co słabo działa w językach bez spacji między słowami. Tokenizer trigram dzieli tekst co 3 znaki, umożliwiając dopasowywanie podłańcuchów kosztem rozmiaru indeksu (około 3 razy większego).
Utrzymanie
FTS5 wymaga jawnej synchronizacji, gdy bazowa tabela chunks się zmienia:
# After inserting chunks
cursor.execute("""
INSERT INTO chunks_fts(chunks_fts)
VALUES('rebuild')
""")
Polecenie rebuild rekonstruuje indeks FTS5 na podstawie tabeli treści. Należy uruchamiać je po operacjach wstawiania zbiorczego (pełne ponowne indeksowanie), ale nie po pojedynczych aktualizacjach przyrostowych — w ich przypadku należy używać INSERT INTO chunks_fts(rowid, chunk_text, section, heading_context), aby synchronizować pojedyncze wiersze.
Wyszukiwanie wektorowe z sqlite-vec
Rozszerzenie sqlite-vec wprowadza wyszukiwanie wektorowe KNN (K-Nearest Neighbors) do SQLite. Ta sekcja omawia konfigurację sqlite-vec, pipeline embeddingów od notatki do przeszukiwalnego wektora oraz konkretne wzorce zapytań.
Tabela wirtualna sqlite-vec
CREATE VIRTUAL TABLE chunk_vecs USING vec0(
id INTEGER PRIMARY KEY,
embedding float[256]
);
Moduł vec0 przechowuje 256-wymiarowe wektory float jako spakowane dane binarne. Kolumna id mapuje się 1:1 na tabelę chunks, umożliwiając złączenia między wynikami wektorowymi a metadanymi fragmentów.
Pipeline embeddingów
Pipeline prowadzi od notatki do przeszukiwalnego wektora:
Note (.md file)
→ Chunker: split at H2 boundaries
→ Chunks (30-2000 chars each)
→ Credential filter: scrub secrets
→ Embedder: Model2Vec encode
→ Vectors (256-dim float arrays)
→ sqlite-vec: store as packed binary
→ Ready for KNN queries
Serializacja wektorów
Moduł struct w Python serializuje wektory float na potrzeby przechowywania w sqlite-vec:
import struct
def _serialize_vector(vec):
"""Pack float list into binary for sqlite-vec."""
return struct.pack(f"{len(vec)}f", *vec)
def _deserialize_vector(blob, dim=256):
"""Unpack binary blob to float list."""
return list(struct.unpack(f"{dim}f", blob))
Zapytanie KNN
Zapytanie wyszukiwania wektorowego tworzy embedding zapytania wejściowego, a następnie znajduje K najbliższych fragmentów według odległości cosinusowej:
def _vector_search(self, query_text, limit=30):
query_vec = self.embedder.embed_batch([query_text])[0]
packed = _serialize_vector(query_vec)
results = self.db.execute("""
SELECT
cv.id,
cv.distance,
c.file_path,
c.section,
c.chunk_text
FROM chunk_vecs cv
JOIN chunks c ON cv.id = c.id
WHERE embedding MATCH ?
AND k = ?
ORDER BY distance
""", [packed, limit]).fetchall()
return results
Operator MATCH w sqlite-vec wykonuje przybliżone wyszukiwanie najbliższych sąsiadów. Parametr k kontroluje liczbę zwracanych wyników. Kolumna distance zawiera odległość cosinusową (0 = identyczne, 2 = przeciwne).
Paginacja KNN z ograniczeniami odległości
Od sqlite-vec v0.1.7 zapytania KNN obsługują ograniczenia WHERE distance < ?, umożliwiając paginację opartą na kursorze przez duże zestawy wyników bez ponownego skanowania wcześniejszych stron.14 Późniejsze stabilne wydania v0.1.8 i v0.1.9 to wydania dotyczące pakietowania oraz poprawek błędów DELETE, a nie nowe wydania modelu zapytań, dlatego v0.1.7 pozostaje granicą funkcji dla tego wzorca paginacji.23
def _paginated_vector_search(self, query_vec, page_size=20, max_distance=None):
"""Paginate through KNN results using distance constraints."""
packed = _serialize_vector(query_vec)
constraint = f"AND distance < {max_distance}" if max_distance else ""
results = self.db.execute(f"""
SELECT cv.id, cv.distance, c.file_path, c.chunk_text
FROM chunk_vecs cv
JOIN chunks c ON cv.id = c.id
WHERE embedding MATCH ?
AND k = ?
{constraint}
ORDER BY distance
""", [packed, page_size]).fetchall()
# Use last result's distance as cursor for next page
next_cursor = results[-1][1] if results else None
return results, next_cursor
Zastępuje to wcześniejszy wzorzec pobierania dużego k i wycinania wyników w Python, zmniejszając użycie pamięci przy eksploracyjnych zapytaniach w dużych vaultach.
Obsługa DELETE w tabelach vec0
sqlite-vec v0.1.7 dodał natywną obsługę DELETE dla tabel wirtualnych vec0, a v0.1.9 naprawił ścieżkę błędu DELETE związaną z tekstowymi kolumnami metadanych dłuższymi niż 12 znaków.1423 Wcześniej usuwanie wektorów wymagało porzucenia i ponownego utworzenia tabeli. Teraz ścieżka usuwania plików w indexerze może usuwać wektory bezpośrednio:
# Before v0.1.7: required workaround (drop + recreate, or mark as inactive)
# After v0.1.7: direct DELETE works
db.execute("DELETE FROM chunk_vecs WHERE id = ?", [chunk_id])
Upraszcza to przyrostowe ponowne indeksowanie, gdy notatki zostają usunięte lub przeniesione. Indexer nie musi już utrzymywać pomocniczej tabeli „aktywnych ID” ani wykonywać odbudowy wsadowej.
Kiedy wyszukiwanie wektorowe wygrywa
Wyszukiwanie wektorowe sprawdza się najlepiej w zapytaniach, w których pojęcie jest ważniejsze niż konkretne słowa:
- Zapytanie: „how to handle authentication failures” → znajduje notatki o „login error recovery” (ta sama przestrzeń semantyczna, inne słowa kluczowe)
- Zapytanie: „what patterns exist for caching” → znajduje notatki o „memoization”, „Redis TTL strategies” i „HTTP cache headers” (powiązane pojęcia, zróżnicowana terminologia)
- Zapytanie: „approaches to testing asynchronous code” → znajduje notatki o „pytest-asyncio fixtures”, „mock event loops” i „async test patterns” (to samo pojęcie wyrażone przez szczegóły implementacji)
Kiedy wyszukiwanie wektorowe zawodzi
Wyszukiwanie wektorowe ma trudności z dokładnymi identyfikatorami:
- Zapytanie:
_rrf_fuse→ zwraca notatki o „fusion algorithms” i „rank merging”, ale może umieścić właściwą definicję funkcji niżej niż omówienia koncepcyjne - Zapytanie:
PostToolUse→ zwraca notatki o „tool lifecycle hooks” i „post-execution handlers” zamiast konkretnej nazwy hooka
Wyszukiwanie wektorowe ma też trudności z danymi strukturalnymi. Pliki konfiguracyjne JSON, bloki YAML i fragmenty kodu generują embeddingi, które przechwytują wzorce strukturalne zamiast znaczenia semantycznego. Plik JSON z "review": true osadza się inaczej niż prozatorskie omówienie code review.
Łagodna degradacja
Jeśli sqlite-vec nie załaduje się (brakujące rozszerzenie, niezgodna platforma, uszkodzona biblioteka), retriever przechodzi awaryjnie na wyszukiwanie wyłącznie BM25:
class VectorIndex:
def __init__(self, db_path):
self.db = sqlite3.connect(db_path)
self._vec_available = False
try:
self.db.enable_load_extension(True)
self.db.load_extension("vec0")
self._vec_available = True
except Exception:
pass # BM25-only mode
@property
def vec_available(self):
return self._vec_available
Retriever sprawdza vec_available przed próbą wykonania zapytań wektorowych. Gdy funkcja jest wyłączona, wszystkie wyszukiwania używają wyłącznie BM25, a krok fuzji RRF jest pomijany.
Reciprocal Rank Fusion (RRF)
RRF scala dwie listy rankingowe bez konieczności kalibracji wyników. Ta sekcja omawia algorytm, prześledzone zapytanie, strojenie parametru k oraz powody wyboru RRF zamiast alternatyw. Interaktywny kalkulator z edytowalnymi rankingami, presetami scenariuszy i wizualnym eksploratorem architektury znajduje się w szczegółowym omówieniu mechanizmu wyszukiwania hybrid.
Algorytm
RRF przypisuje każdemu dokumentowi wynik wyłącznie na podstawie jego pozycji rankingowej na każdej liście:
score(d) = Σ (weight_i / (k + rank_i))
Gdzie:
- k to stała wygładzająca (60, zgodnie z Cormack et al.3)
- rank_i to liczona od 1 pozycja dokumentu na liście wyników i
- weight_i to opcjonalny mnożnik dla danej listy (domyślnie 1.0)
Dokumenty wysoko sklasyfikowane na wielu listach otrzymują wyższe wyniki po scaleniu. Dokumenty, które pojawiają się tylko na jednej liście, otrzymują wynik wyłącznie z tego jednego źródła.
Dlaczego RRF zamiast alternatyw
Ważona kombinacja liniowa wymaga kalibracji wyników BM25 względem odległości kosinusowych. Wyniki BM25 są nieograniczone i skalują się wraz z rozmiarem korpusu. Odległości kosinusowe są ograniczone do zakresu [0, 2]. Ich połączenie wymaga normalizacji, a parametry normalizacji zależą od zestawu danych. RRF używa wyłącznie pozycji rankingowych, które zawsze są liczbami całkowitymi zaczynającymi się od 1, niezależnie od metody punktacji.
Wyuczone modele fuzji wymagają oznaczonych danych treningowych — par zapytanie-dokument z oceną trafności. W przypadku osobistej bazy wiedzy takie dane treningowe nie istnieją. Trzeba byłoby ręcznie ocenić setki par zapytanie-dokument, aby wytrenować użyteczny model. RRF działa bez żadnych danych treningowych.
Metody głosowania Condorceta (Borda count, Schulze method) są teoretycznie eleganckie, ale bardziej złożone w implementacji i strojeniu. Oryginalna praca o RRF wykazała, że RRF przewyższa metody Condorceta na danych ewaluacyjnych TREC.3
Fuzja w praktyce
Zapytanie: „how does the review aggregator handle disagreements”
BM25 umieszcza review-aggregator.py na pozycji 3 (dokładne dopasowania słów kluczowych „review”, „aggregator”, „disagreements”), ale wyżej klasyfikuje dwa pliki konfiguracyjne (ponieważ słowo „review” występuje w nich bardziej eksponowanie). Wyszukiwanie wektorowe umieszcza ten sam chunk na pozycji 1 (semantyczne dopasowanie do rozwiązywania konfliktów). Po fuzji RRF:
| Chunk | BM25 | Vec | Wynik po scaleniu |
|---|---|---|---|
| review-aggregator.py “Disagreement Resolution” | #3 | #1 | 0.0323 |
| code-review-patterns.md “Multi-Reviewer” | #4 | #2 | 0.0317 |
| deliberation-config.json “Review Weights” | #1 | — | 0.0164 |
Na szczyt trafiają chunki, które wysoko plasują się na obu listach. Chunki pojawiające się tylko na jednej liście dostają wynik z pojedynczego źródła i spadają poniżej wyników sklasyfikowanych podwójnie. Rzeczywista logika rozwiązywania niezgodności wygrywa, ponieważ znalazły ją obie metody — BM25 przez słowa kluczowe, a wyszukiwanie wektorowe przez semantykę.
Pełny ślad krok po kroku z obliczeniami RRF dla każdej pozycji rankingowej oraz różnymi wartościami k można sprawdzić w interaktywnym kalkulatorze RRF.
Implementacja
RRF_K = 60
def _rrf_fuse(self, bm25_results, vec_results,
bm25_weight=1.0, vec_weight=1.0):
"""Fuse BM25 and vector results using Reciprocal Rank Fusion."""
scores = {}
for rank, r in enumerate(bm25_results, start=1):
cid = r["id"]
if cid not in scores:
scores[cid] = {
"rrf_score": 0.0,
"file_path": r["file_path"],
"section": r["section"],
"chunk_text": r["chunk_text"],
"bm25_rank": None,
"vec_rank": None,
}
scores[cid]["rrf_score"] += bm25_weight / (self._rrf_k + rank)
scores[cid]["bm25_rank"] = rank
for rank, r in enumerate(vec_results, start=1):
cid = r["id"]
if cid not in scores:
scores[cid] = {
"rrf_score": 0.0,
"file_path": r["file_path"],
"section": r["section"],
"chunk_text": r["chunk_text"],
"bm25_rank": None,
"vec_rank": None,
}
scores[cid]["rrf_score"] += vec_weight / (self._rrf_k + rank)
scores[cid]["vec_rank"] = rank
fused = sorted(
scores.values(),
key=lambda x: x["rrf_score"],
reverse=True,
)
return fused
Strojenie k
Stała k kontroluje, jak dużą wagę otrzymują wyniki z najwyższych pozycji względem wyników z dalszych miejsc:
- Niższe k (np. 10): Wyniki z najwyższych pozycji dominują. Pozycja 1 daje wynik 1/11 = 0,091, pozycja 10 daje 1/20 = 0,050 (różnica 1,8x). To dobre ustawienie, gdy ufa się poszczególnym rankerom, że poprawnie wybiorą najlepszy wynik.
- Domyślne k (60): Zbalansowane. Pozycja 1 daje wynik 1/61 = 0,0164, pozycja 10 daje 1/70 = 0,0143 (różnica 1,15x). Różnice rankingowe są kompresowane, co zwiększa wagę obecności na wielu listach.
- Wyższe k (np. 200): Obecność na obu listach ma znacznie większe znaczenie niż sama pozycja rankingowa. Pozycja 1 daje 1/201, pozycja 10 daje 1/210 — niemal identycznie. Warto użyć tego ustawienia, gdy poszczególne rankery generują zaszumione rankingi, ale zgodność między listami jest wiarygodna.
Proszę zacząć od k=60. Oryginalna praca o RRF uznała tę wartość za solidną w zróżnicowanych zestawach danych TREC. Strojenie warto przeprowadzać dopiero po zmierzeniu przypadków niepowodzeń na własnym rozkładzie zapytań.
Rozstrzyganie remisów
Gdy dwa chunki mają identyczne wyniki RRF (rzadkie, ale możliwe przy tej samej pozycji na jednej liście i braku obecności na drugiej), remisy należy rozstrzygać następująco:
- Preferować chunki, które pojawiają się na obu listach, względem chunków pojawiających się tylko na jednej
- Wśród chunków obecnych na obu listach preferować ten z niższą łączną pozycją
- Wśród chunków obecnych tylko na jednej liście preferować ten z niższą pozycją na tej liście
Pełny pipeline wyszukiwania
Ta sekcja prowadzi zapytanie od wejścia do wyjścia przez cały pipeline: wyszukiwanie BM25, wyszukiwanie wektorowe, fuzję RRF, przycinanie budżetu tokenów oraz składanie kontekstu.
Przepływ od początku do końca
User query: "PostToolUse hook for context compression"
│
├─ BM25 Search (FTS5)
│ → MATCH "PostToolUse hook context compression"
│ → Top 30 results ranked by BM25 score
│ → 12ms
│
├─ Vector Search (sqlite-vec)
│ → Embed query with Model2Vec
│ → KNN k=30 on chunk_vecs
│ → Top 30 results ranked by cosine distance
│ → 8ms
│
└─ RRF Fusion
→ Merge 60 candidates (may overlap)
→ Score by rank position
→ Top 10 results
→ 3ms
│
└─ Token Budget
→ Truncate to max_tokens (default 4000)
→ Estimate at 4 chars per token
→ Return results with metadata
→ <1ms
Całkowite opóźnienie: ~23ms dla bazy danych obejmującej 49 746 fragmentów na sprzęcie Apple M3 Pro.
Search API
class HybridRetriever:
def search(self, query, limit=10, max_tokens=4000,
bm25_weight=1.0, vec_weight=1.0):
"""
Search the vault using hybrid BM25 + vector retrieval.
Args:
query: Search query text
limit: Maximum results to return
max_tokens: Token budget for total result text
bm25_weight: Weight for BM25 results in RRF
vec_weight: Weight for vector results in RRF
Returns:
List of SearchResult with file_path, section,
chunk_text, rrf_score, bm25_rank, vec_rank
"""
# BM25 search
bm25_results = self._bm25_search(query, limit=30)
# Vector search (if available)
if self.index.vec_available:
vec_results = self._vector_search(query, limit=30)
fused = self._rrf_fuse(
bm25_results, vec_results,
bm25_weight, vec_weight,
)
else:
fused = bm25_results # BM25-only fallback
# Token budget truncation
results = []
token_count = 0
for r in fused[:limit]:
chunk_tokens = len(r["chunk_text"]) // 4
if token_count + chunk_tokens > max_tokens:
break
results.append(r)
token_count += chunk_tokens
return results
Przycinanie budżetu tokenów
Parametr max_tokens zapobiega zwracaniu przez retriever większego kontekstu, niż narzędzie AI może wykorzystać. Szacunek zakłada 4 znaki na token (rozsądne przybliżenie dla prozy angielskiej). Wyniki są przycinane zachłannie: dodawane są w kolejności rankingu, aż budżet zostanie wyczerpany.
To strategia konserwatywna. Bardziej zaawansowane podejście uwzględniałoby oceny jakości poszczególnych wyników i preferowało krótsze wyniki o wyższej jakości zamiast dłuższych wyników o niższej jakości. Podejście zachłanne jest prostsze i dobrze sprawdza się w praktyce, ponieważ ranking RRF już porządkuje wyniki według trafności.
Schemat bazy danych (pełny)
-- Chunk content and metadata
CREATE TABLE chunks (
id INTEGER PRIMARY KEY,
file_path TEXT NOT NULL,
section TEXT NOT NULL,
chunk_text TEXT NOT NULL,
heading_context TEXT DEFAULT '',
mtime_ns INTEGER NOT NULL,
embedded_at REAL NOT NULL
);
CREATE INDEX idx_chunks_file ON chunks(file_path);
CREATE INDEX idx_chunks_mtime ON chunks(mtime_ns);
-- FTS5 for BM25 search (content-synced to chunks table)
CREATE VIRTUAL TABLE chunks_fts USING fts5(
chunk_text, section, heading_context,
content=chunks, content_rowid=id
);
-- sqlite-vec for vector KNN search
CREATE VIRTUAL TABLE chunk_vecs USING vec0(
id INTEGER PRIMARY KEY,
embedding float[256]
);
-- Model metadata for compatibility tracking
CREATE TABLE model_meta (
key TEXT PRIMARY KEY,
value TEXT
);
Ścieżka graceful degradation
Full pipeline: BM25 + Vector + RRF → Best results
No sqlite-vec: BM25 only → Good results (no semantic)
No model download: BM25 only → Good results (no semantic)
No FTS5: Vector only → Decent results (no keyword)
No database: Error → Prompt user to run indexer
Retriever sprawdza możliwości podczas inicjalizacji i dostosowuje strategię zapytań. Brakujący komponent obniża jakość, ale nie powoduje błędów. Jedyną twardą awarią jest brak pliku bazy danych.
Statystyki produkcyjne
Pomiar wykonany na vault Obsidian obejmującym 16 894 pliki, 49 746 fragmentów, bazę SQLite o rozmiarze 83 MB, Apple M3 Pro:
| Metryka | Wartość |
|---|---|
| Łączna liczba plików | 16 894 |
| Łączna liczba fragmentów | 49 746 |
| Rozmiar bazy danych | 83 MB |
| Opóźnienie zapytania BM25 (p50) | 12ms |
| Opóźnienie zapytania wektorowego (p50) | 8ms |
| Opóźnienie fuzji RRF | 3ms |
| Opóźnienie wyszukiwania od początku do końca (p50) | 23ms |
| Czas pełnego ponownego indeksowania | ~4 minuty |
| Czas przyrostowego ponownego indeksowania | <10 sekund |
| Model embeddingów | potion-base-8M (256-dim) |
| Pula kandydatów BM25 | 30 |
| Pula kandydatów wektorowych | 30 |
| Domyślny limit wyników | 10 |
| Domyślny budżet tokenów | 4 000 tokenów |
Hashowanie treści i wykrywanie zmian
Indekser musi wiedzieć, które pliki zmieniły się od ostatniego uruchomienia indeksu. Ta sekcja omawia mechanizm wykrywania zmian oraz strategię hashów.
Porównanie czasu modyfikacji pliku
Indekser przechowuje mtime_ns (czas modyfikacji pliku w nanosekundach) dla każdego fragmentu w tabeli chunks. Podczas uruchomienia przyrostowego indekser:
- Skanuje vault Obsidian pod kątem wszystkich plików
.mdw dozwolonych folderach - Odczytuje
mtime_nsdla każdego pliku z systemu plików - Porównuje go z
mtime_nszapisanym w bazie danych - Identyfikuje 3 kategorie:
- Nowe pliki: ścieżka istnieje w systemie plików, ale nie w bazie danych
- Zmienione pliki: ścieżka istnieje w obu miejscach, ale
mtime_nsjest inny - Usunięte pliki: ścieżka istnieje w bazie danych, ale nie w systemie plików
def get_stale_files(self, vault_mtimes):
"""Find files whose mtime changed or are new."""
stored = dict(self.db.execute(
"SELECT DISTINCT file_path, mtime_ns FROM chunks"
).fetchall())
stale = []
for path, mtime in vault_mtimes.items():
if path not in stored or stored[path] != mtime:
stale.append(path)
return stale
def get_deleted_files(self, vault_paths):
"""Find files in database that no longer exist in vault."""
stored_paths = set(r[0] for r in self.db.execute(
"SELECT DISTINCT file_path FROM chunks"
).fetchall())
return stored_paths - set(vault_paths)
Dlaczego mtime, a nie hash treści
Hashowanie treści (SHA-256 zawartości pliku) byłoby bardziej niezawodne niż porównanie mtime — wykrywałoby przypadki, w których plik został dotknięty bez zmiany treści (np. git checkout przywracający pierwotny mtime). Hashowanie wymaga jednak odczytania każdego pliku przy każdym uruchomieniu przyrostowym. Dla 16 894 plików odczyt zawartości plików zajmuje 2-3 sekundy. Odczyt mtimes z systemu plików zajmuje <100ms.
Kompromis: porównanie mtime sporadycznie uruchamia niepotrzebne ponowne indeksowanie niezmienionych plików (wyniki fałszywie dodatnie), ale nigdy nie pomija rzeczywistych zmian. Wyniki fałszywie dodatnie kosztują kilka dodatkowych wywołań embeddingów na uruchomienie. Różnica szybkości (100ms kontra 3 sekundy) sprawia, że mtime jest pragmatycznym wyborem dla systemu uruchamianego przy każdej interakcji z AI.
Obsługa usunięć
Gdy plik zostaje usunięty z vault Obsidian, indekser usuwa wszystkie jego fragmenty z bazy danych:
def remove_file(self, file_path):
"""Remove all chunks and vectors for a file."""
chunk_ids = [r[0] for r in self.db.execute(
"SELECT id FROM chunks WHERE file_path = ?",
[file_path],
).fetchall()]
for cid in chunk_ids:
self.db.execute(
"DELETE FROM chunk_vecs WHERE id = ?", [cid]
)
self.db.execute(
"DELETE FROM chunks WHERE file_path = ?",
[file_path],
)
Instrukcja DELETE FROM chunk_vecs działa natywnie od sqlite-vec v0.1.7, z poprawką błędu w v0.1.9 dla operacji DELETE na tabelach vec0 z dłuższymi kolumnami tekstu metadanych.1423 Wcześniejsze wersje wymagały obejść (usunięcia i ponownego utworzenia tabeli wirtualnej albo utrzymywania zewnętrznego zestawu „active IDs”). Jeśli używana jest wersja sprzed 0.1.9, należy wykonać upgrade przed poleganiem na bezpośrednich usunięciach w schematach intensywnie korzystających z metadanych.
Tabele synchronizacji treści FTS5 wymagają jawnego usunięcia przez INSERT INTO chunks_fts(chunks_fts, rowid, ...) VALUES('delete', ?, ...) dla każdego usuniętego wiersza. Indekser obsługuje to jako część procesu usuwania pliku.
Indeksowanie przyrostowe vs pełne ponowne indeksowanie
Indekser obsługuje 2 tryby: przyrostowy (szybki, do codziennego użycia) i pełny (wolny, okazjonalny). W tej sekcji omówiono, kiedy używać każdego z nich, gwarancje idempotencji oraz odzyskiwanie po uszkodzeniu danych.
Indeksowanie przyrostowe
Kiedy używać: Do codziennego indeksowania po edycji notatek. To tryb domyślny.
Co robi: 1. Skanuje magazyn notatek pod kątem zmian w plikach (porównanie mtime) 2. Usuwa fragmenty dla usuniętych plików 3. Ponownie dzieli na fragmenty i ponownie generuje embeddings dla zmienionych plików 4. Wstawia nowe fragmenty dla nowych plików 5. Synchronizuje indeks FTS5
Typowy czas trwania: <10 sekund dla dziennych zmian w magazynie z 16 000 plików.
python index_vault.py --incremental
Pełne ponowne indeksowanie
Kiedy używać: - Po zmianie modelu embeddings (wykryta niezgodność hasha modelu) - Po migracji schematu (nowe kolumny, zmienione indeksy) - Po uszkodzeniu bazy danych (kontrola integralności kończy się niepowodzeniem) - Gdy indeksowanie przyrostowe daje nieoczekiwane wyniki
Co robi: 1. Usuwa wszystkie istniejące dane (fragmenty, wektory, wpisy FTS5) 2. Skanuje cały magazyn notatek 3. Dzieli wszystkie pliki na fragmenty 4. Generuje embeddings dla wszystkich fragmentów 5. Buduje indeks FTS5 od zera
Typowy czas trwania: ~4 minuty dla 16 894 plików na Apple M3 Pro.
python index_vault.py --full
Idempotencja
Oba tryby są idempotentne: dwukrotne uruchomienie tego samego polecenia daje ten sam wynik. Indekser usuwa istniejące fragmenty dla pliku przed wstawieniem nowych, więc ponowne uruchomienie indeksowania przyrostowego na już aktualnej bazie danych nie wprowadza żadnych zmian. Ponowne uruchomienie pełnego indeksowania tworzy identyczną bazę danych.
Odzyskiwanie po uszkodzeniu danych
Jeśli baza SQLite zostanie uszkodzona (utrata zasilania podczas zapisu, błąd dysku, przerwany proces w trakcie transakcji):
# Check integrity
sqlite3 vectors.db "PRAGMA integrity_check;"
# If corruption detected, full reindex rebuilds from source files
python index_vault.py --full
Źródłem prawdy są zawsze pliki w magazynie notatek, nie baza danych. Baza danych jest artefaktem pochodnym, który można odbudować w dowolnym momencie. To kluczowa właściwość projektu: nie trzeba nigdy tworzyć kopii zapasowej bazy danych.
Flaga --incremental
Gdy indekser działa z --incremental:
- Sprawdzenie hasha modelu. Porównuje zapisany hash modelu z bieżącym modelem. Jeśli jest inny, automatycznie przełącza się w tryb pełnego ponownego indeksowania i ostrzega użytkownika.
- Skanowanie plików. Przechodzi przez dozwolone foldery, zbiera ścieżki plików i wartości mtime.
- Wykrywanie zmian. Porównuje je z zapisanymi danymi.
- Przetwarzanie wsadowe. Ponownie dzieli zmienione pliki na fragmenty i ponownie generuje embeddings w partiach po 64.
- Raportowanie postępu. Wypisuje liczbę przetworzonych plików i czas, który upłynął.
- Łagodne zamykanie. Obsługuje SIGINT, kończąc bieżący plik przed zatrzymaniem.
Filtrowanie poświadczeń i granice danych
Osobiste notatki zawierają sekrety: klucze API, bearer tokens, ciągi połączeń z bazą danych, klucze prywatne wklejone podczas sesji debugowania. Filtr poświadczeń zapobiega ich trafieniu do indeksu wyszukiwania.
Problem
Notatka o debugowaniu integracji OAuth może zawierać:
The token was: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
I used this curl command:
curl -H "Authorization: Bearer sk-ant-api03-abc123..."
Bez filtrowania zarówno JWT, jak i klucz API zostałyby podzielone na fragmenty, przetworzone na embeddings i zapisane w bazie danych. Wyszukiwanie hasła „authentication” zwróciłoby fragment zawierający prawdziwe sekrety. Co gorsza, jeśli retriever przekaże wyniki do narzędzia AI przez MCP, sekrety pojawią się w oknie kontekstu AI i potencjalnie w logach narzędzia.
Filtrowanie oparte na wzorcach
Filtr poświadczeń uruchamia się dla każdego fragmentu przed zapisem, dopasowując 25 wzorców specyficznych dla dostawców oraz wzorce ogólne:
Wzorce specyficzne dla dostawców:
| Wzorzec | Przykład | Regex |
|---|---|---|
| Klucz OpenAI API | sk-... |
sk-[a-zA-Z0-9_-]{20,} |
| Klucz Anthropic API | sk-ant-api03-... |
sk-ant-api\d{2}-[a-zA-Z0-9_-]{20,} |
| GitHub PAT | ghp_... |
gh[ps]_[a-zA-Z0-9]{36,} |
| AWS Access Key | AKIA... |
AKIA[0-9A-Z]{16} |
| Klucz Stripe | sk_live_... |
[sr]k_(live\|test)_[a-zA-Z0-9]{24,} |
| Token Cloudflare | ... |
Różne wzorce |
Wzorce ogólne:
| Wzorzec | Wykrywanie |
|---|---|
| Tokeny JWT | eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+ |
| Bearer tokens | Bearer\s+[a-zA-Z0-9_\-\.]+ |
| Klucze prywatne | -----BEGIN (RSA\|EC\|OPENSSH) PRIVATE KEY----- |
| Base64 o wysokiej entropii | Ciągi z entropią >4,5 bitu/znak, 40+ znaków |
| Przypisania haseł | password\s*[:=]\s*["'][^"']+["'] |
Implementacja filtra
def clean_content(text):
"""Scrub credentials from text before indexing."""
result = ScanResult(is_clean=True, match_count=0, patterns=[])
for pattern in CREDENTIAL_PATTERNS:
matches = pattern.regex.findall(text)
if matches:
text = pattern.regex.sub(
f"[REDACTED:{pattern.name}]", text
)
result.is_clean = False
result.match_count += len(matches)
result.patterns.append(pattern.name)
return text, result
Kluczowe decyzje projektowe:
-
Filtrowanie przed embeddings. Oczyszczony tekst jest tym, dla czego generowane są embeddings. Reprezentacja wektorowa nigdy nie koduje wzorców poświadczeń. Zapytanie o „klucz API” zwraca notatki omawiające zarządzanie kluczami API, a nie notatki zawierające rzeczywiste klucze.
-
Zastępowanie, nie usuwanie. Token
[REDACTED:pattern-name]zachowuje semantyczny kontekst otaczającego tekstu. Embedding uchwyci, że „było tu coś przypominającego poświadczenie”, bez kodowania samego poświadczenia. -
Logowanie wzorców, nie wartości. Filtr loguje, które wzorce zostały dopasowane (np. „Scrubbed 2 credential(s) from oauth-debug.md [jwt, bearer-token]”), ale nigdy nie loguje wartości poświadczenia.
Wykluczanie na podstawie ścieżki
Plik .indexignore zapewnia ogólne wykluczanie według ścieżki. Filtr poświadczeń zapewnia dokładne oczyszczanie wewnątrz indeksowanych plików. Oba mechanizmy są potrzebne:
.indexignoredla całych folderów, o których wiadomo, że zawierają wrażliwe treści (notatki zdrowotne, dokumenty finansowe, dokumenty zawodowe)- Filtr poświadczeń dla sekretów przypadkowo osadzonych w treści, która poza tym nadaje się do indeksowania
Klasyfikacja danych
W przypadku magazynów notatek zawierających zróżnicowane treści warto rozważyć klasyfikowanie notatek według wrażliwości:
| Poziom | Przykłady | Indeksować? | Filtrować? |
|---|---|---|---|
| Publiczne | Szkice blogowe, notatki techniczne | Tak | Tak |
| Wewnętrzne | Plany projektów, decyzje architektoniczne | Tak | Tak |
| Wrażliwe | Dane o wynagrodzeniu, dokumentacja zdrowotna | Nie (.indexignore) | Nie dotyczy |
| Ograniczone | Poświadczenia, klucze prywatne | Nie (.indexignore) | Nie dotyczy |
Architektura serwera MCP
Serwery Model Context Protocol (MCP) udostępniają mechanizm wyszukiwania jako narzędzie, które mogą wywoływać agenci AI. Ta sekcja omawia projekt serwera, zakres funkcji oraz granice uprawnień.
Wybór protokołu: STDIO a HTTP
MCP obsługuje 2 tryby transportu:
STDIO — Narzędzie AI uruchamia serwer MCP jako proces podrzędny i komunikuje się z nim przez stdin/stdout. To standardowy tryb dla narzędzi lokalnych. Claude Code, Codex CLI i Cursor obsługują serwery MCP działające przez STDIO.
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/path/to/vault",
"DB_PATH": "/path/to/vectors.db"
}
}
}
}
HTTP — Serwer MCP działa jako samodzielna usługa HTTP. Przydaje się przy dostępie zdalnym, konfiguracjach z wieloma klientami lub konfiguracjach zespołowych, w których vault znajduje się na współdzielonym serwerze.
{
"mcpServers": {
"obsidian": {
"url": "http://localhost:3333/mcp"
}
}
}
Rekomendacja: W przypadku osobistych vaultów warto używać STDIO. Jest prostszy, bezpieczniejszy (brak ekspozycji sieciowej), a cyklem życia serwera zarządza narzędzie AI. HTTP należy używać tylko wtedy, gdy wiele narzędzi lub wiele maszyn potrzebuje jednoczesnego dostępu do tego samego vaultu.
Ewolucja specyfikacji MCP. Specyfikacja MCP z czerwca 2025 roku dodała autoryzację OAuth 2.1, ustrukturyzowane dane wyjściowe narzędzi (typowane schematy zwrotne) oraz elicitation (monity użytkownika inicjowane przez serwer). Wydanie z listopada 2025 roku wprowadziło Streamable HTTP jako pełnoprawny tryb transportu, wykrywanie URL-i
.well-knowndo automatycznego przeglądania możliwości serwera, ustrukturyzowane adnotacje narzędzi deklarujące, czy narzędzie jest tylko do odczytu, czy modyfikuje dane, oraz system standaryzacji poziomów SDK.79 Następne wydanie specyfikacji (wstępnie planowane na połowę 2026 roku) proponuje operacje asynchroniczne dla długotrwałych zadań, branżowe rozszerzenia protokołu dla sektorów takich jak opieka zdrowotna i finanse oraz standardy komunikacji agent-to-agent dla przepływów pracy z wieloma agentami.9 W przypadku osobistych serwerów vaultów STDIO pozostaje najprostszą ścieżką. Transport Streamable HTTP oraz wykrywanie.well-knownprzynoszą korzyści głównie wdrożeniom korporacyjnym HTTP z routingiem wielodzierżawnym i równoważeniem obciążenia. Warto śledzić plan rozwoju MCP, aby zauważyć aktualizacje wpływające na wybór transportu.
Projektowanie możliwości
Serwer MCP powinien udostępniać minimalny zestaw narzędzi:
search — Główne narzędzie. Uruchamia hybrid retrieval i zwraca uszeregowane wyniki.
{
"name": "obsidian_search",
"description": "Search the Obsidian vault using hybrid BM25 + vector retrieval",
"parameters": {
"query": { "type": "string", "description": "Search query" },
"limit": { "type": "integer", "default": 5 },
"max_tokens": { "type": "integer", "default": 2000 }
}
}
read_note — Odczytuje pełną zawartość konkretnej notatki według ścieżki. Przydatne, gdy agent chce zobaczyć pełny kontekst wyniku wyszukiwania.
{
"name": "obsidian_read_note",
"description": "Read the full content of a note by file path",
"parameters": {
"file_path": { "type": "string", "description": "Relative path within vault" }
}
}
list_notes — Wyświetla notatki pasujące do filtra (według folderu, tagu, typu lub zakresu dat). Przydatne do eksploracji, gdy agent nie ma konkretnego zapytania.
{
"name": "obsidian_list_notes",
"description": "List notes matching filters",
"parameters": {
"folder": { "type": "string", "description": "Folder path within vault" },
"tag": { "type": "string", "description": "Tag to filter by" },
"limit": { "type": "integer", "default": 20 }
}
}
get_context — Narzędzie pomocnicze, które uruchamia wyszukiwanie i formatuje wyniki jako blok kontekstu odpowiedni do wstrzyknięcia do rozmowy.
{
"name": "obsidian_get_context",
"description": "Get formatted context from vault for a topic",
"parameters": {
"topic": { "type": "string", "description": "Topic to get context for" },
"max_tokens": { "type": "integer", "default": 2000 }
}
}
Granice uprawnień
Serwer MCP powinien wymuszać ścisłe granice:
-
Tylko do odczytu. Serwer odczytuje vault i bazę danych indeksu. Nie tworzy, nie modyfikuje ani nie usuwa notatek. Operacje zapisu (przechwytywanie nowych notatek) są obsługiwane przez osobne hooks lub skills, a nie przez serwer MCP.
-
Ograniczony do vaultu. Serwer odczytuje wyłącznie pliki znajdujące się w skonfigurowanej ścieżce vaultu. Próby path traversal (
../../etc/passwd) muszą być odrzucane. -
Dane wyjściowe filtrowane pod kątem poświadczeń. Nawet jeśli baza danych zawiera wstępnie przefiltrowaną treść, należy zastosować filtrowanie poświadczeń na wyjściu jako mechanizm defense-in-depth.
-
Odpowiedzi ograniczone tokenami. Należy wymuszać
max_tokensdla wszystkich odpowiedzi narzędzi, aby zapobiec otrzymywaniu przez narzędzie AI nadmiernie dużych bloków kontekstu.
Obsługa błędów
Narzędzia MCP powinny zwracać ustrukturyzowane komunikaty o błędach, które pomagają narzędziu AI odzyskać kontrolę po problemie:
def search(self, query, limit=5, max_tokens=2000):
if not self.db_path.exists():
return {
"error": "Index database not found. Run the indexer first.",
"suggestion": "python index_vault.py --full"
}
results = self.retriever.search(query, limit, max_tokens)
if not results:
return {
"results": [],
"message": f"No results found for '{query}'. Try broader terms."
}
return {
"results": [
{
"file_path": r["file_path"],
"section": r["section"],
"text": r["chunk_text"],
"score": round(r["rrf_score"], 4),
}
for r in results
],
"count": len(results),
"query": query,
}
Integracja Claude Code
Claude Code jest głównym konsumentem systemu wyszukiwania Obsidian. Ta sekcja omawia konfigurację MCP, integrację hooków oraz wzorzec obsidian_bridge.py.
Konfiguracja MCP
Dodać serwer MCP Obsidian do ~/.claude/settings.json:
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/absolute/path/to/vault",
"DB_PATH": "/absolute/path/to/vectors.db"
}
}
}
}
Po dodaniu konfiguracji należy ponownie uruchomić Claude Code. Serwer MCP uruchomi się jako proces potomny. Aby sprawdzić, czy działa:
> What tools do you have from the obsidian MCP server?
Claude Code powinien wyświetlić dostępne narzędzia (obsidian_search, obsidian_read_note itd.).
Integracja hooków
Hooki rozszerzają działanie Claude Code w określonych punktach cyklu życia. Dla integracji z Obsidian istotne są dwa hooki:
Hook PreToolUse — odpytuje skarbiec, zanim agent przetworzy wywołanie narzędzia. Automatycznie wstrzykuje odpowiedni kontekst.
#!/bin/bash
# ~/.claude/hooks/pre-tool-use/obsidian-context.sh
# Automatically inject vault context before tool execution
TOOL_NAME="$1"
PROMPT="$2"
# Only inject context for code-related tools
case "$TOOL_NAME" in
Edit|Write|Bash)
# Query the vault
CONTEXT=$(python /path/to/retriever.py search "$PROMPT" --limit 3 --max-tokens 1500)
if [ -n "$CONTEXT" ]; then
echo "---"
echo "Relevant vault context:"
echo "$CONTEXT"
echo "---"
fi
;;
esac
Hook PostToolUse — zapisuje istotne wyniki działania narzędzi z powrotem do skarbca, aby można było je później odnaleźć.
#!/bin/bash
# ~/.claude/hooks/post-tool-use/capture-insight.sh
# Capture significant outputs to vault (selective)
TOOL_NAME="$1"
OUTPUT="$2"
# Only capture substantial outputs
if [ ${#OUTPUT} -gt 500 ]; then
python /path/to/capture.py --text "$OUTPUT" --source "claude-code-$TOOL_NAME"
fi
Wzorzec obsidian_bridge.py
Moduł pomostowy udostępnia Python API, który mogą wywoływać hooki i skills:
# obsidian_bridge.py
from retriever import HybridRetriever
_retriever = None
def get_retriever():
global _retriever
if _retriever is None:
_retriever = HybridRetriever(
db_path="/path/to/vectors.db",
vault_path="/path/to/vault",
)
return _retriever
def search_vault(query, limit=5, max_tokens=2000):
"""Search vault and return formatted context."""
retriever = get_retriever()
results = retriever.search(query, limit, max_tokens)
if not results:
return ""
lines = ["## Vault Context\n"]
for r in results:
lines.append(f"**{r['file_path']}** — {r['section']}")
lines.append(f"> {r['chunk_text'][:500]}")
lines.append("")
return "\n".join(lines)
Skill /capture
Skill Claude Code do zapisywania spostrzeżeń z powrotem w skarbcu:
/capture "OAuth token rotation requires both access and refresh token invalidation"
--domain security
--tags oauth,tokens
Skill tworzy nową notatkę w 00-inbox/ z poprawnym frontmatter i wyzwala przyrostowe ponowne indeksowanie, dzięki czemu nową notatkę można od razu wyszukać.
Wzorce niestandardowych poleceń
Skills Claude Code mogą opakowywać operacje na skarbcu w nazwane polecenia. Praktycy budowali biblioteki poleceń specyficznych dla Obsidian, które traktują skarbiec jednocześnie jako źródło odczytu i cel zapisu.
Skanowanie sygnałów. Polecenie /scan-intel odpytuje źródła zewnętrzne, ocenia znaleziska względem osobistych zainteresowań badawczych i zapisuje kwalifikujące się sygnały jako notatki w skarbcu z frontmatter:
/scan-intel --topics "agent infrastructure, security" --lookback 7d
Polecenie pobiera dane ze skonfigurowanych źródeł (arXiv, HN, RSS), stosuje model punktacji (trafność, możliwość działania, głębia, autorytet) i zapisuje sygnały spełniające kryteria w tematycznych folderach skarbca. Skarbiec staje się odbiorcą końcowym zautomatyzowanego potoku analitycznego.
Dziennik kapitana. Polecenie /captains-log agreguje dzienną aktywność git we wszystkich repozytoriach, zapisuje uporządkowany wpis dziennika w skarbcu i uwzględnia podjęte decyzje, odkrycia oraz otwarte wątki:
/captains-log
Polecenie pobiera historię commitów z GitHub, grupuje ją według repozytorium i formatuje jako narracyjny wpis dziennika. Z czasem dzienne logi tworzą przeszukiwalny zapis tego, co zostało dostarczone i dlaczego.
Przechwytywanie do Obsidian. Polecenie /obsidian-capture pobiera spostrzeżenie z bieżącej sesji Claude Code i zapisuje je bezpośrednio w skarbcu z poprawnymi metadanymi:
/obsidian-capture "SAST gates in agent loops increase security degradation"
--folder AI-Tools --tags security,agents
Ten wzorzec można rozszerzyć na dowolną operację na skarbcu: tworzenie MOCs, aktualizowanie notatek statusu projektu, łączenie powiązanych sygnałów czy generowanie tygodniowych podsumowań z nagromadzonych dziennych logów.
Przykłady społeczności. Praktycy publikują swoje biblioteki poleceń. Jeden deweloper udostępnił 22 niestandardowe polecenia Obsidian + Claude Code, obejmujące dzienne przeglądy, planowanie projektów, przechwytywanie badań i workflowy treści.1 Inny zbudował skill „Visual Explainer”, który generuje notatki z diagramami w skarbcu na podstawie analizy kodu.2 Polecenia się różnią, ale architektura pozostaje spójna: skills Claude Code jako interfejs, notatki w skarbcu jako warstwa przechowywania, a infrastruktura wyszukiwania jako silnik zapytań.
Zarządzanie oknem kontekstu
Integracja powinna uwzględniać okno kontekstu Claude Code:
- Ograniczyć wstrzykiwany kontekst do 1 500-2 000 tokenów na zapytanie. Większa ilość konkuruje z pamięcią roboczą agenta.
- Uwzględniać atrybucję źródła. Zawsze należy dołączyć ścieżkę pliku i nagłówek sekcji, aby agent mógł odwołać się do źródła.
- Przycinać tekst chunków. Długie chunki należy skracać za pomocą
..., zamiast całkowicie je pomijać. Pierwsze 300-500 znaków zwykle zawiera kluczowe informacje. - Nie wstrzykiwać kontekstu przy każdym wywołaniu narzędzia. Hook PreToolUse powinien selektywnie wstrzykiwać kontekst na podstawie wywoływanego narzędzia. Operacje odczytu nie wymagają kontekstu skarbca. Operacje Write i Edit z niego korzystają.
Integracja Codex CLI
Codex CLI łączy się z serwerami MCP przez config.toml. Wzorzec integracji różni się od Claude Code składnią konfiguracji i sposobem przekazywania instrukcji.
Konfiguracja MCP
Dodać do .codex/config.toml lub ~/.codex/config.toml:
[mcp_servers.obsidian]
command = "python"
args = ["/path/to/obsidian_mcp.py"]
[mcp_servers.obsidian.env]
VAULT_PATH = "/absolute/path/to/vault"
DB_PATH = "/absolute/path/to/vectors.db"
Wzorce AGENTS.md
Codex CLI odczytuje AGENTS.md w celu pobrania instrukcji na poziomie projektu. Należy uwzględnić wskazówki dotyczące przeszukiwania skarbca:
## Available Tools
### Obsidian Vault (MCP: obsidian)
Use the `obsidian_search` tool to find relevant context from the knowledge base.
Search the vault when you need:
- Background on a concept or pattern
- Prior decisions or rationale
- Reference material for implementation
Example queries:
- "authentication patterns in FastAPI"
- "how does the review aggregator work"
- "sqlite-vec configuration"
Różnice względem Claude Code
| Funkcja | Claude Code | Codex CLI |
|---|---|---|
| Konfiguracja MCP | settings.json |
config.toml |
| Hooki | ~/.claude/hooks/ |
Nieobsługiwane |
| Skills | ~/.claude/skills/ |
Nieobsługiwane |
| Plik instrukcji | CLAUDE.md |
AGENTS.md |
| Tryby zatwierdzania | --dangerously-skip-permissions |
suggest / auto-edit / full-auto |
Kluczowa różnica: Codex CLI nie obsługuje hooków. Wzorzec automatycznego wstrzykiwania kontekstu (hook PreToolUse) nie jest dostępny. Zamiast tego należy umieścić w AGENTS.md jawne instrukcje nakazujące agentowi przeszukanie skarbca przed rozpoczęciem pracy.
Cursor i inne narzędzia
Cursor i inne narzędzia AI obsługujące MCP mogą łączyć się z tym samym serwerem MCP Obsidian. W tej sekcji omówiono konfigurację popularnych narzędzi.
Cursor
Do pliku .cursor/mcp.json w katalogu głównym projektu należy dodać:
{
"mcpServers": {
"obsidian": {
"command": "python",
"args": ["/path/to/obsidian_mcp.py"],
"env": {
"VAULT_PATH": "/absolute/path/to/vault",
"DB_PATH": "/absolute/path/to/vectors.db"
}
}
}
}
Plik .cursorrules Cursor może zawierać instrukcje korzystania z magazynu:
When working on implementation tasks, search the Obsidian vault
for relevant context before writing code. Use the obsidian_search
tool with descriptive queries about the concept you're implementing.
Macierz zgodności
| Narzędzie | Obsługa MCP | Transport | Lokalizacja konfiguracji |
|---|---|---|---|
| Claude Code | Pełna | STDIO | ~/.claude/settings.json |
| Codex CLI | Pełna | STDIO | .codex/config.toml |
| Cursor | Pełna | STDIO | .cursor/mcp.json |
| Windsurf | Pełna | STDIO | .windsurf/mcp.json |
| Continue.dev | Częściowa | HTTP | ~/.continue/config.json |
| Zed | W trakcie prac | STDIO | Interfejs ustawień |
| Claudian (plugin Obsidian) | Nie dotyczy (wbudowane) | Claude Code CLI | Ustawienia pluginu Obsidian |
| Agent Client (plugin Obsidian) | Nie dotyczy (wbudowane) | ACP | Ustawienia pluginu Obsidian |
Rozwiązanie awaryjne dla narzędzi bez MCP
W przypadku narzędzi, które nie obsługują MCP, retriever można opakować jako CLI:
# Search from command line
python retriever_cli.py search "query text" --limit 5
# Output formatted for copy-paste into any tool
python retriever_cli.py context "query text" --format markdown
CLI zwraca uporządkowany tekst, który można ręcznie wkleić do wejścia dowolnego narzędzia AI. To mniej eleganckie niż integracja z MCP, ale działa uniwersalnie.
Prompt caching ze strukturyzowanych notatek
Strukturyzowane notatki w magazynie mogą służyć jako bloki kontekstu wielokrotnego użytku, które zmniejszają zużycie tokenów w interakcjach z AI. W tej sekcji omówiono projektowanie kluczy cache i zarządzanie budżetem tokenów.
Wzorzec
Zamiast wyszukiwać kontekst przy każdej interakcji, można wcześniej zbudować bloki kontekstu z dobrze uporządkowanych notatek w magazynie i zapisać je w cache:
# cache_keys.py
CONTEXT_BLOCKS = {
"auth-patterns": {
"vault_query": "authentication patterns implementation",
"max_tokens": 1500,
"ttl_hours": 24, # Rebuild daily
},
"api-conventions": {
"vault_query": "API design conventions REST patterns",
"max_tokens": 1000,
"ttl_hours": 168, # Rebuild weekly
},
"project-architecture": {
"vault_query": "current project architecture decisions",
"max_tokens": 2000,
"ttl_hours": 12, # Rebuild twice daily
},
}
Unieważnianie cache
Unieważnianie cache opiera się na dwóch sygnałach:
- Wygaśnięcie TTL. Każdy blok kontekstu ma określony czas życia. Po wygaśnięciu TTL blok jest odbudowywany przez ponowne zapytanie do magazynu.
- Wykrycie zmian w magazynie. Gdy indexer wykryje zmiany w plikach, które przyczyniły się do powstania zapisanego w cache bloku kontekstu, blok jest natychmiast unieważniany.
Zarządzanie budżetem tokenów
Sesja zaczyna się z łącznym budżetem kontekstu. Bloki zapisane w cache zużywają część tego budżetu:
Total context budget: 8,000 tokens
├─ System prompt: 1,500 tokens
├─ Cached blocks: 3,000 tokens (pre-loaded)
├─ Dynamic search: 2,000 tokens (on-demand)
└─ Conversation: 1,500 tokens (remaining)
Bloki zapisane w cache są ładowane przy starcie sesji. Dynamiczne wyniki wyszukiwania wypełniają pozostały budżet osobno dla każdego zapytania. Takie hybrydowe podejście zapewnia agentowi bazowy zestaw często potrzebnego kontekstu, a jednocześnie zachowuje budżet na konkretne zapytania.
Zużycie tokenów przed i po
Bez cache: Każde istotne zapytanie uruchamia wyszukiwanie w magazynie i zwraca 1 500-2 000 tokenów kontekstu. Przy 10 zapytaniach w sesji agent zużywa 15 000-20 000 tokenów kontekstu z magazynu.
Z cache: Trzy wcześniej zbudowane bloki kontekstu zużywają łącznie 4 500 tokenów. Dodatkowe wyszukiwania dodają 1 500-2 000 tokenów na każde unikalne zapytanie. Przy 10 zapytaniach, z których 6 pokrywają bloki zapisane w cache, agent zużywa 4 500 + (4 * 1 500) = 10 500 tokenów, czyli mniej więcej połowę zużycia bez cache.
Hooki PostToolUse do kompresji kontekstu
Wyniki narzędzi mogą być obszerne: stack trace, listy plików, wyniki testów. Hook PostToolUse może skompresować te wyniki, zanim zajmą miejsce w oknie kontekstu.
Problem
Wywołanie narzędzia Bash, które uruchamia testy, może zwrócić:
PASSED tests/test_auth.py::test_login_success
PASSED tests/test_auth.py::test_login_failure
PASSED tests/test_auth.py::test_token_refresh
PASSED tests/test_auth.py::test_session_expiry
... (200 more lines)
FAILED tests/test_api.py::test_rate_limit_exceeded
Pełny wynik ma 5 000 tokenów, ale właściwy sygnał znajduje się w 2 wierszach: 200 zakończonych powodzeniem, 1 zakończony niepowodzeniem.
Implementacja hooka
#!/bin/bash
# ~/.claude/hooks/post-tool-use/compress-output.sh
# Compress verbose tool outputs to preserve context window
TOOL_NAME="$1"
OUTPUT="$2"
OUTPUT_LEN=${#OUTPUT}
# Only compress large outputs
if [ "$OUTPUT_LEN" -lt 2000 ]; then
exit 0 # Pass through unchanged
fi
case "$TOOL_NAME" in
Bash)
# Compress test output
if echo "$OUTPUT" | grep -q "PASSED\|FAILED"; then
PASSED=$(echo "$OUTPUT" | grep -c "PASSED")
FAILED=$(echo "$OUTPUT" | grep -c "FAILED")
FAILURES=$(echo "$OUTPUT" | grep "FAILED")
echo "Tests: $PASSED passed, $FAILED failed"
if [ "$FAILED" -gt 0 ]; then
echo "Failures:"
echo "$FAILURES"
fi
fi
;;
esac
Zapobieganie rekurencyjnemu wyzwalaniu
Hook kompresujący, który emituje wynik, mógłby wyzwolić sam siebie, jeśli nie zostanie zabezpieczony:
# Guard against recursive invocation
if [ -n "$COMPRESS_HOOK_ACTIVE" ]; then
exit 0
fi
export COMPRESS_HOOK_ACTIVE=1
Heurystyki kompresji
| Typ wyniku | Wykrywanie | Strategia kompresji |
|---|---|---|
| Wyniki testów | Słowa kluczowe PASSED / FAILED |
Policzyć sukcesy i niepowodzenia, pokazać tylko niepowodzenia |
| Listy plików | ls lub find w poleceniu |
Skrócić do pierwszych 20 pozycji + liczba |
| Stack trace | Słowo kluczowe Traceback |
Zachować pierwszą i ostatnią ramkę + komunikat błędu |
| Status Git | modified: / new file: |
Podsumować liczby według statusu |
| Wynik budowania | warning: / error: |
Usunąć wiersze informacyjne, zachować ostrzeżenia i błędy |
Potok przyjmowania i selekcji sygnałów
Warstwa przyjmowania decyduje o tym, co trafia do skarbca. Bez kuracji skarbiec gromadzi szum. Ta sekcja omawia potok oceniania, który kieruje sygnały do folderów domenowych.
Źródła
Sygnały pochodzą z wielu kanałów:
- Kanały RSS: blogi techniczne, biuletyny bezpieczeństwa, informacje o wydaniach
- Zakładki przez Web Clipper: oficjalne rozszerzenie Obsidian Web Clipper (Chrome, Firefox, Safari) to ścieżka przyjmowania o najwyższej wierności do przechwytywania treści z poziomu przeglądarki. Cykl wydań z kwietnia 2026 roku sprawił, że stało się ono znacznie bardziej użyteczne w przepływach pracy AI:22
- 1.4.0 (9 kwi): interaktywny interfejs transkrypcji YouTube — można przypiąć wideo, przewijać transkrypcję, automatycznie przewijać widok i podświetlać bieżącą pozycję. Do tego domyślna opcja „Open in Reader”, która jednym kliknięciem wysyła przechwycony materiał bezpośrednio do trybu Reader.
- 1.5.0–1.5.1 (15 kwi): przeglądarka podświetleń — przeglądanie i wyszukiwanie przechwyconych podświetleń w całym skarbcu. Przejście fade-in do Reader. Płynniejsze odtwarzanie/wstrzymywanie YouTube. Wersja 1.5.1 naprawiła regresję kompilacji webpack.
- 1.6.0–1.6.2 (21–23 kwi): przebudowa UX podświetlania z obsługą urządzeń mobilnych. Defuddle 0.18 dodaje ekstraktory specyficzne dla źródeł, takich jak LinkedIn, Threads, Bluesky, Discourse i Medium. Wersja 1.6.2 naprawia regresję schowka w trybie osadzonym Safari. Szablony należy konfigurować dla każdej domeny źródłowej, aby transkrypcje YouTube, pliki README GitHub i długie artykuły trafiały do sensownie nazwanych notatek z właściwym frontmatter dla poniższego potoku oceniania.
- Newslettery: kluczowe fragmenty z newsletterów e-mailowych
- Ręczne przechwytywanie: notatki tworzone podczas czytania, rozmów lub badań
- Wyniki narzędzi: istotne wyniki narzędzi AI przechwycone przez hooks
- Share Extension w iOS: aplikacja Obsidian na iOS (zaktualizowana na początku 2026 roku) zawiera Share Extension, które zapisuje treści z Safari, sieci społecznościowych i innych aplikacji bezpośrednio do skarbca, bez otwierania Obsidian.19 Tworzy to mało tarciową ścieżkę przyjmowania z urządzeń mobilnych — wystarczy udostępnić artykuł z Safari, a pojawi się on jako notatka w skarbcu, gotowa do oceny.
- Obsidian CLI: skrypty powłoki i hooks mogą tworzyć notatki przez
obsidian file createalbo dopisywać treść do istniejących notatek przezobsidian file append, umożliwiając automatyczne potoki przyjmowania na komputerze.
Wymiary oceny
Każdy sygnał jest oceniany w czterech wymiarach (każdy od 0,0 do 1,0):
| Wymiar | Pytanie | Niska ocena (0,0–0,3) | Wysoka ocena (0,7–1,0) |
|---|---|---|---|
| Trafność | Czy odnosi się to do moich aktywnych obszarów? | Poboczne, poza zakresem | Bezpośrednio związane z aktywną pracą |
| Możliwość działania | Czy można wykorzystać tę informację? | Czysta teoria, bez zastosowania | Konkretna technika lub wzorzec do zastosowania |
| Głębia | Jak merytoryczna jest treść? | Nagłówki, płytkie streszczenie | Szczegółowa analiza z przykładami |
| Autorytet | Jak wiarygodne jest źródło? | Anonimowy blog, brak weryfikacji | Źródło pierwotne, recenzowane, uznany ekspert |
Ocena złożona i routing
composite = (relevance * 0.35) + (actionability * 0.25) +
(depth * 0.25) + (authority * 0.15)
| Zakres oceny | Działanie |
|---|---|
| 0,55+ | Automatyczne skierowanie do folderu domenowego |
| 0,40 - 0,55 | Kolejka do ręcznej weryfikacji |
| < 0,40 | Odrzucenie (nie przechowywać) |
Routing domenowy
Sygnały z oceną powyżej 0,55 trafiają do jednego z 12 folderów domenowych na podstawie dopasowania słów kluczowych i klasyfikacji tematu:
05-signals/
├── ai-tooling/ # Claude, LLMs, AI development tools
├── security/ # Vulnerabilities, auth, cryptography
├── systems/ # Architecture, distributed systems
├── programming/ # Languages, patterns, algorithms
├── web/ # Frontend, backends, APIs
├── data/ # Databases, data engineering
├── devops/ # CI/CD, containers, infrastructure
├── design/ # UI/UX, product design
├── mobile/ # iOS, Android, cross-platform
├── career/ # Industry trends, hiring, growth
├── research/ # Academic papers, whitepapers
└── other/ # Signals that don't fit a domain
Statystyki produkcyjne
W ciągu 14 miesięcy działania:
| Metryka | Wartość |
|---|---|
| Łączna liczba przetworzonych sygnałów | 7 771 |
| Skierowane automatycznie (>0,55) | 4 832 (62%) |
| W kolejce do weryfikacji (0,40–0,55) | 1 543 (20%) |
| Odrzucone (<0,40) | 1 396 (18%) |
| Aktywne foldery domenowe | 12 |
| Średnia liczba sygnałów dziennie | ~18 |
Wzorce knowledge graph
Graf wiki-link w Obsidian koduje relacje między notatkami. Ta sekcja omawia semantykę linków, przechodzenie po grafie w celu rozszerzania kontekstu oraz antywzorce obniżające jakość grafu.
Semantyka backlink
Każdy wiki-link tworzy w grafie krawędź skierowaną. Obsidian śledzi zarówno linki wychodzące, jak i backlinks:
- Link wychodzący: notatka A zawiera
[[Note B]]→ A linkuje do B - Backlink: notatka B pokazuje, że notatka A się do niej odwołuje
Graf koduje różne typy relacji w zależności od kontekstu:
| Wzorzec linku | Semantyka | Przykład |
|---|---|---|
| Link w treści | „Jest powiązane z” | „Zobacz [[OAuth Token Rotation]], aby poznać szczegóły” |
| Link nagłówkowy | „Ma podtemat” | „## Related\n- [[Token Rotation]]\n- [[Session Management]]” |
| Link podobny do tagu | „Jest skategoryzowane jako” | „[[type/reference]]” |
| Link MOC | „Jest częścią” | Notatka Map of Content z listą powiązanych notatek |
Maps of Content (MOCs)
MOCs to notatki indeksowe, które porządkują powiązane notatki w strukturę możliwą do nawigowania:
---
title: "Authentication & Security MOC"
type: moc
domain: security
---
## Core Concepts
- [[OAuth 2.0 Overview]]
- [[JWT Token Anatomy]]
- [[Session Management Patterns]]
## Implementation Patterns
- [[OAuth Token Rotation]]
- [[Refresh Token Security]]
- [[PKCE Flow Implementation]]
## Failure Modes
- [[Token Expiry Handling]]
- [[Session Fixation Prevention]]
- [[CSRF Defense Strategies]]
MOCs wspierają retrieval na dwa sposoby:
- Bezpośrednie dopasowanie. Wyszukiwanie „authentication overview” dopasowuje sam MOC, dostarczając agentowi wyselekcjonowaną listę powiązanych notatek.
- Rozszerzanie kontekstu. Po znalezieniu konkretnej notatki retriever może sprawdzić, czy występuje ona w jakichkolwiek MOCs, i dołączyć strukturę MOC do wyników, dając agentowi mapę szerszego tematu.
Przechodzenie po grafie w celu rozszerzania kontekstu
Przyszłe usprawnienie retrievera: po znalezieniu najlepszych wyników można rozszerzyć kontekst przez podążanie za linkami:
def expand_context(results, depth=1):
"""Follow wiki-links from top results to find related context."""
expanded = set()
for result in results:
# Parse wiki-links from chunk text
links = extract_wiki_links(result["chunk_text"])
for link_target in links:
# Resolve link to file path
target_path = resolve_wiki_link(link_target)
if target_path and target_path not in expanded:
expanded.add(target_path)
# Include target's most relevant chunk
target_chunks = get_chunks_for_file(target_path)
# ... rank and include best chunk
return results + list(expanded_results)
Nie jest to zaimplementowane w obecnym retrieverze, ale stanowi naturalne rozszerzenie struktury grafu.
Antywzorce
Osierocone klastry. Grupy notatek, które linkują do siebie nawzajem, ale nie mają połączeń z resztą skarbca. Panel grafu w Obsidian pokazuje je jako odłączone wyspy. Osierocone klastry wskazują na brakujące MOCs albo brakujące linki między domenami.
Rozrost tagów. Niespójne używanie tagów lub tworzenie zbyt wielu drobnoziarnistych tagów. Skarbiec z 500 unikalnymi tagami w 5 000 notatkach ma średnio 1 notatkę na 10 tagów — takie tagi nie są przydatne do filtrowania. Należy skonsolidować je do 20–50 tagów wysokiego poziomu, które odpowiadają folderom domenowym.
Notatki bogate w linki, ubogie w treść. Notatki składające się wyłącznie z wiki-link bez prozy. Takie notatki słabo się indeksują, ponieważ chunker nie ma tekstu do osadzenia. Warto dodać co najmniej jeden akapit kontekstu wyjaśniający, dlaczego linkowane notatki są ze sobą powiązane.
Dwukierunkowe linki do wszystkiego. Nie każde odwołanie musi być wiki-link. Przelotne wspomnienie „OAuth” nie wymaga [[OAuth 2.0 Overview]]. Wiki-link należy rezerwować dla intencjonalnych, możliwych do nawigowania relacji, w których kliknięcie linku dostarcza użytecznego kontekstu.
Przepisy dotyczące pracy deweloperskiej
Praktyczne przepływy pracy, które łączą wyszukiwanie w skarbcu z codziennymi zadaniami deweloperskimi.
Poranne ładowanie kontekstu
Dzień warto rozpocząć od załadowania odpowiedniego kontekstu:
Search my vault for notes about [current project] updated in the last week
Retriever zwraca najnowsze notatki dotyczące aktywnego projektu, co pozwala szybko przypomnieć sobie, gdzie praca została przerwana. To skuteczniejsze niż ponowne czytanie wczorajszych komunikatów commitów.
Przechwytywanie badań podczas kodowania
Podczas implementowania funkcji można zapisywać spostrzeżenia bez opuszczania edytora:
/capture "FastAPI dependency injection with async generators requires yield,
not return. The generator is the dependency lifecycle."
--domain programming
--tags fastapi,dependency-injection
Zapisana obserwacja jest natychmiast indeksowana i dostępna do przyszłego wyszukiwania. W perspektywie miesięcy takie mikro-notatki budują korpus wiedzy specyficznej dla implementacji.
Rozpoczęcie projektu
Przy rozpoczynaniu nowego projektu lub funkcji:
- Przeszukaj skarbiec: „Co wiem o [technologia/wzorzec]?”
- Przejrzyj 5 najlepszych wyników pod kątem wcześniejszych decyzji i pułapek
- Sprawdź, czy istnieje MOC dla danej domeny; jeśli nie, utwórz go
- Wyszukaj tryby awarii: „problemy z [technologia]”
Debugowanie z wyszukiwaniem w skarbcu
Gdy pojawi się błąd lub nieoczekiwane zachowanie:
Search my vault for [error message or symptom]
Wcześniejsze notatki z debugowania często zawierają przyczynę źródłową i poprawkę. Jest to szczególnie cenne przy powtarzających się problemach w różnych projektach — skarbiec pamięta to, o czym łatwo zapomnieć.
Przygotowanie do przeglądu kodu
Przed przeglądem PR:
Search my vault for patterns and conventions about [module being changed]
Skarbiec zwraca wcześniejsze decyzje, ograniczenia architektoniczne i standardy kodowania istotne dla przeglądanego kodu. Przegląd opiera się na wiedzy instytucjonalnej, a nie tylko na diffie.
Dostrajanie wydajności
Ta sekcja omawia strategie optymalizacji dla różnych rozmiarów skarbca i wzorców użycia.
Zarządzanie rozmiarem indeksu
| Rozmiar skarbca | Fragmenty | Rozmiar DB | Pełna reindeksacja | Przyrostowo |
|---|---|---|---|---|
| 500 notatek | ~1 500 | 3 MB | 15 sekund | <1 sekunda |
| 2 000 notatek | ~6 000 | 12 MB | 45 sekund | 2 sekundy |
| 5 000 notatek | ~15 000 | 30 MB | 2 minuty | 4 sekundy |
| 15 000 notatek | ~50 000 | 83 MB | 4 minuty | <10 sekund |
| 50 000 notatek | ~150 000 | 250 MB | 15 minut | 30 sekund |
Przy ponad 50 000 notatek warto rozważyć: - Zwiększenie rozmiaru batcha z 64 do 128, aby szybciej tworzyć embeddingi - Używanie trybu WAL (domyślnie) do równoległego dostępu - Uruchamianie pełnej reindeksacji poza godzinami pracy
Optymalizacja zapytań
Tryb WAL. Tryb Write-Ahead Logging w SQLite umożliwia równoległe odczyty podczas zapisu przez indekser:
db.execute("PRAGMA journal_mode=WAL")
Ma to krytyczne znaczenie, gdy serwer MCP obsługuje zapytania w czasie, gdy indekser wykonuje aktualizację przyrostową.
Connection pooling. Serwer MCP powinien ponownie wykorzystywać połączenia z bazą danych zamiast otwierać nowe połączenie dla każdego zapytania. Jedno długotrwałe połączenie z trybem WAL obsługuje równoległe odczyty.
# MCP server initialization
db = sqlite3.connect(DB_PATH, check_same_thread=False)
db.execute("PRAGMA journal_mode=WAL")
db.execute("PRAGMA mmap_size=268435456") # 256 MB mmap
Memory-mapped I/O. Pragma mmap_size informuje SQLite, aby używać memory-mapped I/O dla pliku bazy danych. W przypadku bazy danych o rozmiarze 83 MB zmapowanie całego pliku w pamięci eliminuje większość odczytów z dysku.
Optymalizacja FTS5. Po pełnej reindeksacji uruchom:
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
Scali to wewnętrzne segmenty b-tree FTS5, zmniejszając opóźnienie zapytań dla kolejnych wyszukiwań.
Benchmarki skalowania
Pomiar wykonano na Apple M3 Pro, 36 GB RAM, NVMe SSD:
| Operacja | 500 notatek | 5K notatek | 15K notatek | 50K notatek |
|---|---|---|---|---|
| Zapytanie BM25 | 2ms | 5ms | 12ms | 25ms |
| Zapytanie wektorowe | 1ms | 3ms | 8ms | 20ms |
| Fuzja RRF | <1ms | <1ms | 3ms | 5ms |
| Pełne wyszukiwanie | 3ms | 8ms | 23ms | 50ms |
Wszystkie benchmarki obejmują dostęp do bazy danych, wykonanie zapytania i formatowanie wyników. Opóźnienie sieciowe komunikacji MCP STDIO dodaje 1-2ms.
Rozwiązywanie problemów
Dryf indeksu
Objaw: Wyszukiwanie zwraca nieaktualne wyniki lub pomija niedawno dodane notatki.
Przyczyna: Indekser przyrostowy nie został uruchomiony po dodaniu notatek albo mtime pliku nie został zaktualizowany (np. po synchronizacji z innego komputera z zachowanymi znacznikami czasu).
Poprawka: Uruchom pełną reindeksację: python index_vault.py --full
Zmiana modelu embeddingów
Objaw: Po zmianie modelu embeddingów wyszukiwanie wektorowe zwraca bezsensowne wyniki.
Przyczyna: Stare wektory (z poprzedniego modelu) są porównywane z nowymi wektorami zapytania. Wymiary lub semantyka przestrzeni wektorowej są niezgodne.
Poprawka: Indekser powinien wykryć niezgodność hasha modelu i automatycznie uruchomić pełną reindeksację. Jeśli tak się nie stanie, należy ręcznie wyczyścić bazę danych i ponownie ją zindeksować:
rm vectors.db
python index_vault.py --full
Utrzymanie FTS5
Objaw: Zapytania FTS5 zwracają niepoprawne lub niepełne wyniki po wielu aktualizacjach przyrostowych.
Przyczyna: Wewnętrzne segmenty FTS5 mogą ulec fragmentacji po wielu małych aktualizacjach.
Poprawka: Odbuduj i zoptymalizuj:
INSERT INTO chunks_fts(chunks_fts) VALUES('rebuild');
INSERT INTO chunks_fts(chunks_fts) VALUES('optimize');
Timeout MCP
Objaw: Narzędzie AI zgłasza, że serwer MCP przekroczył limit czasu.
Przyczyna: Pierwsze zapytanie uruchamia ładowanie modelu (lazy initialization), co trwa 2-5 sekund. Domyślny timeout MCP w narzędziu AI może być krótszy.
Poprawka: Wstępnie rozgrzej model przy starcie serwera:
# In MCP server initialization
retriever = HybridRetriever(db_path, vault_path)
retriever.search("warmup", limit=1) # Trigger model load
Blokady plików SQLite
Objaw: Błędy SQLITE_BUSY lub SQLITE_LOCKED.
Przyczyna: Wiele procesów zapisuje jednocześnie do bazy danych. Tryb WAL pozwala na równoległe odczyty, ale tylko jednego zapisującego.
Poprawka: Upewnij się, że tylko jeden proces (indekser) zapisuje do bazy danych. Serwer MCP i hooks powinny wyłącznie odczytywać. Jeśli potrzebne są równoległe zapisy, użyj trybu WAL i ustaw busy timeout:
db.execute("PRAGMA busy_timeout=5000") # Wait up to 5 seconds
sqlite-vec się nie ładuje
Objaw: Wyszukiwanie wektorowe jest wyłączone; retriever działa w trybie tylko BM25.
Przyczyna: Rozszerzenie sqlite-vec nie jest zainstalowane, nie znajduje się w ścieżce bibliotek albo jest niezgodne z wersją SQLite.
Poprawka:
# Install via pip
pip install sqlite-vec
# Or compile from source
git clone https://github.com/asg017/sqlite-vec
cd sqlite-vec && make
Sprawdź, czy rozszerzenie się ładuje:
import sqlite3
db = sqlite3.connect(":memory:")
db.enable_load_extension(True)
db.load_extension("vec0")
print("sqlite-vec loaded successfully")
Problemy z pamięcią w dużym skarbcu
Objaw: Błędy braku pamięci podczas pełnej reindeksacji dużego skarbca (ponad 50 000 notatek).
Przyczyna: Rozmiar batcha embeddingów jest zbyt duży albo zawartość wszystkich plików jest ładowana do pamięci jednocześnie.
Poprawka: Zmniejsz rozmiar batcha i przetwarzaj pliki przyrostowo:
BATCH_SIZE = 32 # Reduce from 64
Należy też upewnić się, że indekser przetwarza pliki pojedynczo (czytając, dzieląc na fragmenty i tworząc embeddingi dla każdego pliku przed przejściem do następnego), zamiast ładować wszystkie pliki do pamięci.
Przewodnik migracji
Z Apple Notes
- Wyeksportuj Apple Notes za pomocą opcji „Export All” (macOS) albo użyj narzędzia migracyjnego, takiego jak
apple-notes-liberator - Przekonwertuj eksporty HTML na markdown za pomocą
markdownifylubpandoc - Przenieś przekonwertowane pliki do folderu
00-inbox/w swoim skarbcu - Przejrzyj każdą notatkę i dodaj frontmatter
- Przenieś notatki do odpowiednich folderów domenowych
Z Notion
- Wyeksportuj z Notion: Settings → Export → Markdown & CSV
- Rozpakuj eksport do folderu
00-inbox/w swoim skarbcu - Popraw artefakty markdown specyficzne dla Notion:
- Notion używa
- [ ]dla checklist — to standardowy markdown - Notion uwzględnia tabele właściwości jako HTML — przekonwertuj je na frontmatter YAML
- Notion osadza obrazy jako ścieżki względne — skopiuj obrazy do folderu załączników
- Dodaj standardowy frontmatter (
type,domain,tags) - Zastąp linki stron Notion wiki-linkami Obsidian
Z Google Docs
- Użyj Google Takeout, aby wyeksportować wszystkie dokumenty
- Przekonwertuj pliki
.docxna markdown:pandoc -f docx -t markdown input.docx -o output.md - Wykonaj konwersję wsadową:
for f in *.docx; do pandoc -f docx -t markdown "$f" -o "${f%.docx}.md"; done - Przenieś do skarbca, dodaj frontmatter i uporządkuj w folderach
Ze zwykłego markdown (bez Obsidian)
Jeśli istnieje już katalog plików markdown:
- Otwórz katalog jako skarbiec Obsidian (Obsidian → Open Vault → Open folder)
- Dodaj
.obsidian/do.gitignore, jeśli katalog jest objęty kontrolą wersji - Utwórz szablony frontmatter i zastosuj je do istniejących plików
- Zacznij łączyć notatki za pomocą
[[wiki-links]]podczas czytania i porządkowania - Uruchom indekser od razu — system wyszukiwania działa od pierwszego dnia
Z innego systemu wyszukiwania
Jeśli migracja odbywa się z innego systemu embeddingów/wyszukiwania:
- Nie próbuj migrować wektorów. Różne modele tworzą niezgodne przestrzenie wektorowe. Uruchom pełną reindeksację z nowym modelem.
- Migruj treść, nie indeks. Pliki skarbca są źródłem prawdy. Indeks jest artefaktem pochodnym.
- Zweryfikuj po migracji. Uruchom 10-20 zapytań, na które znasz odpowiedzi, i sprawdź, czy wyniki są zgodne z oczekiwaniami.
Dziennik zmian
| Data | Zmiana |
|---|---|
| 2026-05-28 | Wydano Obsidian 1.13.0 desktop + 1.13.0 mobile (Catalyst early-access). Desktop: przeprojektowany panel ustawień otwierany w osobnym oknie, z wbudowanym wyszukiwaniem i nawigacją klawiaturą; Obsidian URI wyświetlają teraz okno potwierdzenia przed uruchomieniem akcji; nowe ostrzeżenie przed ładowaniem zasobów HTML z dysków sieciowych; dodano wyszukiwanie do widoku Bookmarks; ulepszona obsługa obrazów w edytorze; usprawnienia File Explorer / Properties / Sync; liczne poprawki dla developer-API oraz poprawki błędów. Mobile: nowy iOS Share Sheet z konfigurowalnymi lokalizacjami docelowymi; zmiana kolejności kart z poziomu przełącznika kart; gesty naciśnięcia i przytrzymania na tabletach do zmiany rozmiaru podziałów i przypiętych paneli bocznych; Bases otrzymuje pozycję menu do zmiany rozmiaru kolumn w widokach tabel; poprawki błędów w iOS i wyszukiwaniu. Znaczenie dla przepływów pracy AI: okno potwierdzenia dla Obsidian URI dodaje świadomą bramkę do integracji MCP/agent opartych na URI; menu zmiany rozmiaru kolumn w Bases sprawia, że Bases lepiej nadaje się jako frontowy indeks magazynu, który odpytują agenci; konfigurowalny cel iOS Share Sheet przyspiesza konfigurację ścieżki przechwytywania z iPhone’a (już udokumentowanej jako główny kanał przyjmowania) dla potoków Claude/Codex. |
| 2026-05-06 | Odświeżenie aktualności zweryfikowanej źródłowo: Smart Connections v4.5.0 przeniósł połączenia stopki do Core; stabilne wydania sqlite-vec v0.1.8/v0.1.9 zaktualizowały pakowanie i zachowanie DELETE; Model2Vec v0.8.x zaktualizował wewnętrzne mechanizmy tokenizera/persistencji oraz tabele benchmarków; poprawiono chronologię Obsidian CLI z „1.12.7 wprowadził CLI” na „1.12.0 wprowadził CLI, 1.12.7 ulepszył instalację i pakowanie runtime”. |
| 2026-04-27 | Kwietniowy cykl Web Clipper: 1.4.0 (interaktywny interfejs transkrypcji YouTube + domyślne Open in Reader), 1.5.0 (przeglądarka Highlights), 1.6.0 (przebudowa UX Highlightera + ekstraktory źródeł Defuddle 0.18 dla LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 + 1.6.2 (poprawki Reader i Safari). Przedstawiono Web Clipper jako główną ścieżkę przyjmowania po stronie przeglądarki dla przepływów pracy AI, a nie tylko przelotną wzmiankę o zakładkach. W tym okresie brak wydań Obsidian desktop, Sync lub Bases. |
| 2026-04-16 | Smart Connections v4.3.0 (widok grafu, konfigurowalny dock, odzyskiwanie block-embedding, środowisko Substrate dla wielu wtyczek). Udokumentowano falę wtyczek AI-native z kwietnia 2026 (Cortex, VaultSearch, LLM Wiki, Drift, EngramQuest, Hybrid Search MCP). Oznaczono MarkusPfundstein/mcp-obsidian jako maintenance-mode (ostatni commit w czerwcu 2025). Dataview pozostaje uśpiony; Bases jest następcą dla nowych prac. Obsidian CLI 1.12.7 nadal jest preferowanym mostem dla asystentów AI. |
| 2026-04-01 | Dodano sekcję Obsidian CLI (polecenia v1.12 dla przepływów pracy AI). Dodano sekcję wtyczek agentowych (Claudian, Agent Client). Udokumentowano podstawową wtyczkę Bases do organizacji magazynu. Zaktualizowano liczbę wtyczek do 2500+. Dodano iOS Share Extension jako źródło przyjmowania. Zaktualizowano macierz zgodności z osadzonymi wtyczkami agentowymi. |
| 2026-03-30 | MCPVault v0.11.0: narzędzie list_all_tags, obsługa .base/.canvas, zmiana nazwy na @bitbonsai/mcpvault. Obsidian Desktop v1.12.7 zawiera binarium CLI dla szybszych interakcji terminalowych. |
| 2026-03-23 | Udokumentowano stabilne sqlite-vec v0.1.7: obsługa DELETE dla tabel vec0, ograniczenia dystansu KNN do paginacji. Zapowiedziano indeks DiskANN approximate nearest neighbor w nadchodzącym wydaniu. |
| 2026-03-07 | Dodano potion-multilingual-128M (101 języków, maj 2025) do porównania modeli embeddingowych. sqlite-vec w wersji v0.1.7-alpha.10 (poprawki CI/CD, bez zmian funkcjonalnych). Potwierdzono aktualność specyfikacji MCP i technik wyszukiwania. |
| 2026-03-03 | Zaktualizowano ewolucję specyfikacji MCP (wydanie z listopada 2025: Streamable HTTP, .well-known, adnotacje narzędzi). Dodano fine-tuning Model2Vec oraz obsługę tokenizera BPE/Unigram. Dodano tabelę porównawczą społecznościowych serwerów MCP. Zaktualizowano Smart Connections do v4. |
| 2026-03-02 | Dodano potion-base-32M i potion-retrieval-32M do porównania modeli. Dodano sekcję o kwantyzacji i redukcji wymiarowości. Dodano notatkę o ewolucji specyfikacji MCP. |
| 2026-03-01 | Pierwsze wydanie |
Źródła
-
Internet Vin, „22 commands I use with Obsidian and Claude Code”, marzec 2026, x.com/internetvin/status/2026461256677245131. ↩
-
Nicopreme, skill agenta „Visual Explainer” z poleceniami slash, x.com/nicopreme/status/2023495040258261460. ↩
-
Cormack, G.V., Clarke, C.L.A. i Buettcher, S. Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods. SIGIR, 2009. Wprowadza RRF z k=60 jako metodę bezparametrową do łączenia list rankingowych. ↩↩↩
-
OpenAI Embeddings Pricing. text-embedding-3-small: 0,02 USD za milion tokenów. Szacowany koszt pełnego ponownego indeksowania vault: ~0,30 USD. ↩
-
van Dongen, T. et al. Model2Vec: Turn any Sentence Transformer into a Small Fast Model. arXiv, 2025. Opisuje podejście destylacyjne tworzące statyczne embeddings z sentence transformers. ↩
-
potion-base-8M Model Card i Model2Vec results. Aktualne opublikowane tabele podają potion-base-8M na poziomie 51.32 Avg (All) / 51.08 Avg (MTEB), w porównaniu z all-MiniLM-L6-v2 na poziomie 55.80 Avg (All) / 55.93 Avg (MTEB), czyli około 92% zachowania wyniku dla wszystkich zadań. ↩
-
Model Context Protocol Specification. Standard MCP do łączenia narzędzi AI ze źródłami danych. ↩
-
Model2Vec Potion Models, potion-base-32M i potion-retrieval-32M. Aktualne karty modeli podają potion-base-32M na poziomie 52.83 Avg (All), a potion-retrieval-32M na poziomie 35.06 w tabeli retrieval. ↩↩↩
-
Update on the Next MCP Protocol Release. Wydanie z listopada 2025 r. dostarczyło transport Streamable HTTP, wykrywanie adresów URL .well-known, strukturalne adnotacje narzędzi oraz standaryzację warstw SDK. Kolejne wydanie wstępnie planowane jest na połowę 2026 r. i ma obejmować operacje asynchroniczne, rozszerzenia dziedzinowe oraz komunikację agent-to-agent. ↩↩
-
Model2Vec Releases. v0.4.0 (luty 2025): obsługa trenowania i fine-tuningu. v0.5.0 (kwiecień 2025): przepisanie backendu, kwantyzacja, redukcja wymiarowości. v0.7.0 (październik 2025): kwantyzacja słownika, obsługa tokenizera BPE/Unigram. v0.8.0/v0.8.1 (marzec 2026): refaktoryzacje tokenizera i utrwalania, wycofanie Python 3.9, aktualizacje wyników MTEB V2 oraz zgodność ze ścieżkami Windows. ↩↩
-
Smart Connections for Obsidian. Smart Connections v4: lokalne AI embeddings, wyszukiwanie semantyczne działa offline po początkowym indeksowaniu. ↩
-
potion-multilingual-128M. Minish Lab, maj 2025. Statyczny model embeddingów dla 101 języków, najlepsze wielojęzyczne statyczne embeddings. Ta sama zależność wyłącznie od numpy co w innych modelach potion. ↩
-
MCPVault v0.11.0. Marzec 2026. Nowe narzędzie
list_all_tagsdo skanowania frontmatter i hashtagów wraz z licznikami. Ulepszona obsługa folderów z kropkami oraz obsługa plików.basei.canvas. Pakiet zmienił nazwę na@bitbonsai/mcpvaultw npm. ↩ -
sqlite-vec v0.1.7 Release. 17 marca 2026 r. Stabilne wydanie: obsługa DELETE dla tabel wirtualnych vec0, ograniczenia odległości KNN dla paginacji, ulepszenia testów fuzz. Indeksowanie przybliżonego najbliższego sąsiada DiskANN zapowiedziano w przyszłym wydaniu. ↩↩↩
-
Introduction to Bases. Podstawowa wtyczka Obsidian wprowadzona w v1.9.10. Widoki podobne do baz danych (tabele, galerie, kalendarze, tablice kanban) nad plikami vault z użyciem właściwości frontmatter jako pól. Pliki zapisywane są w formacie
.base. ↩ -
Obsidian Desktop v1.12.0 Changelog i Obsidian Desktop v1.12.7 Changelog. v1.12.0 wprowadziło CLI do terminalowej automatyzacji vault; v1.12.7 ulepszyło instalację i pakowanie środowiska uruchomieniowego dzięki samodzielnemu plikowi binarnemu, TUI oraz zachowaniu pliku socket. Zob. także dokumentację CLI. ↩↩
-
Claudian. Wtyczka Obsidian, która osadza Claude Code jako współpracownika AI w vault. Zapewnia czat na pasku bocznym, prompty świadome kontekstu, obsługę wizji, slash commands i tryby uprawnień. ↩
-
Agent Client. Wtyczka Obsidian zapewniająca ujednolicony interfejs dla Claude Code, Codex CLI i Gemini CLI przez Agent Client Protocol (ACP). Obsługuje wzmianki o notatkach, wykonywanie powłoki i zatwierdzanie działań. ↩
-
Obsidian iOS Changelog. Aktualizacje z początku 2026 r. obejmują Share Extension do zapisywania treści z innych aplikacji bezpośrednio w vault, poprawki widżetów Daily Note i Bookmark oraz ulepszenia odświeżania widżetu View Note. ↩
-
MarkusPfundstein/mcp-obsidian. Ostatni commit 28 czerwca 2025 r. Brak oznaczonych wydań. Dyskusje na forum (kwiecień 2026) wskazują migrację społeczności do integracji opartej na CLI, odkąd Obsidian 1.12.x dostarczył pełnoprawny CLI. Zachowane w tym przewodniku dla kontekstu historycznego i dla użytkowników z istniejącymi konfiguracjami, ale niezalecane dla nowych wdrożeń. ↩↩
-
Smart Connections v4.5.0 Release. 5 maja 2026 r. Połączenia w stopce stały się funkcją Core; najnowsze wydania v4 obejmują też widoki grafu dla list połączeń, konfigurowalne lokalizacje panelu połączeń, ulepszone odzyskiwanie block-embedding, stan Substrate między wtyczkami, poprawki fallbacku transformera oraz ograniczenie zduplikowanych obliczeń połączeń. ↩
-
obsidianmd/obsidian-clipper releases — główne źródło mapowania wersji Web Clipper na funkcje. Cykl z kwietnia 2026 r.: 1.4.0 (9 kwietnia, interfejs transkrypcji YouTube + domyślne Open in Reader), 1.5.0 (15 kwietnia, przeglądarka Highlights + pojawianie się Reader), 1.5.1 (15 kwietnia, poprawka kompilacji webpack), 1.6.0 (21 kwietnia, UX Highlighter + Defuddle 0.18 z ekstraktorami LinkedIn/Threads/Bluesky/Discourse/Medium), 1.6.1 (22 kwietnia, poprawki konspektu Reader + wyszukiwanie highlights), 1.6.2 (23 kwietnia, poprawka schowka w trybie osadzonym Safari). Wpisane także w Mozilla Add-ons store i Chrome Web Store. ↩
-
sqlite-vec v0.1.8, sqlite-vec v0.1.9 i sqlite-vec v0.1.10-alpha.3. v0.1.8 naprawiło pakowanie npm; v0.1.9 naprawiło błąd DELETE dla tekstowych kolumn metadanych dłuższych niż 12 znaków; v0.1.10-alpha.3 dodaje poprawną obsługę
INSERT OR REPLACE INTO, ale jest wersją prerelease. ↩↩↩