벼리 is the head-rope of a fishing net — pull it and the whole net follows. That is what retrieval should do for your notes: pull the right thread, the rest comes with it.
Headless hybrid search for a folder of Markdown notes. No app, no GPU, no cloud.
byeori indexes a Markdown vault (Obsidian or any .md folder) locally with a
static embedding model, then answers queries by fusing lexical (exact, via ripgrep)
and semantic (meaning, via vectors) results. It runs on a laptop, a cron job, a CI
runner, or an air-gapped server — no Obsidian app running, no torch/GPU, no API key.
Most "semantic search for Obsidian" tools live inside the app — the app must be open, embeddings are tied to a plugin, and you can't script it. byeori is the opposite: it is a headless CLI you can put anywhere.
| byeori | app-bound plugin search | |
|---|---|---|
| Runs without the app open | ✅ | ❌ |
| Scriptable (cron, CI, MCP, pipelines) | ✅ | ✖ usually |
| GPU / torch required | ❌ none | often |
| Data leaves the machine | ❌ local by default | varies |
| Lexical + semantic in one rank | ✅ RRF | rarely |
| Korean / cross-lingual | ✅ multilingual model | varies |
Good fit: small teams and solo operators who want private, low-cost, customizable retrieval over their own knowledge base — including Korean / mixed-language vaults.
pip install byeori # from PyPI (once published)
# or, from source:
pip install git+https://github.com/peterkimpmp/byeoriOptional but recommended: install ripgrep
(brew install ripgrep / apt install ripgrep) for the fast lexical leg.
# 1) build the index (incremental — only changed chunks re-embed on later runs)
byeori index ~/notes
# 2) (optional) start a warm server so queries are ~tens of ms instead of ~1s
byeori serve ~/notes &
# 3) search — hybrid by default
byeori search ~/notes "회의 후 결정된 액션 아이템 정리"
byeori search ~/notes "model evaluation metrics" --mode semantic --top-k 5 --jsonFirst run downloads a ~tens-of-MB static model from the Hugging Face Hub; after that everything is local.
- Chunking — splits each note on
#/##/###headings and prepends a small frontmatter context line (title · tags · topic), so a chunk carries its own context. - Embedding — model2vec static embeddings
(numpy only, no torch/GPU). Default
minishlab/potion-multilingual-128M(Korean + English + more). Swap viaBYEORI_MODEL. - Store — a single numpy
.npzflat matrix in<vault>/.byeori/(gitignored). Incremental: each chunk is keyed by a content hash, so re-indexing only embeds what changed. - Hybrid retrieval — lexical hits (ripgrep) and semantic hits (cosine top-k) are
merged with Reciprocal Rank Fusion (
score = Σ 1/(60+rank)), the standard parameter-light fusion (Cormack et al., 2009). If there is no index or no embedder, byeori degrades gracefully to lexical-only. - Warm server — the cost of semantic search is dominated by loading the model
once (~1s), not the search (~tens of ms).
byeori servekeeps the model and index resident behind a unix socket;searchuses it automatically when present.
| Env var | Default | Meaning |
|---|---|---|
BYEORI_MODEL |
minishlab/potion-multilingual-128M |
local static embedding model |
BYEORI_REMOTE_MODEL |
text-embedding-3-small |
model used with --remote |
--remote switches to OpenAI embeddings (higher quality, but your text leaves the
machine — opt-in only; requires pip install "byeori[remote]" and OPENAI_API_KEY).
- Static embeddings are fast, not state-of-the-art. model2vec trades some precision
for speed and zero-GPU. For higher recall/precision, set
BYEORI_MODELto a stronger model, or use--remote. Korean is supported (multilingual) but not specially tuned. - numpy flat store is great up to a few hundred thousand chunks; beyond that a
sqlite-vec/hnswlibbackend (planned) is the right move. - No reranking in v1 (a cross-encoder reranker is a natural future add).
- This is a focused retrieval tool, not a full RAG framework.
A query that names a concept in different words than your notes is where semantic search earns its keep. Compare modes:
byeori search ~/notes "직원 번아웃 예방" --mode lexical --json
byeori search ~/notes "직원 번아웃 예방" --mode hybrid --jsonThe hybrid set should surface conceptually-related notes (and cross-lingual matches)
that pure lexical misses. See tests/ for a runnable check.
Apache-2.0. Patent grant + permissive reuse, suitable for commercial and enterprise use. Third-party attributions in NOTICE.
byeori is the open, give-away retrieval layer; it is intentionally small and independent.
Made by Project Research · contributions welcome (see CONTRIBUTING.md).