Skip to content

peterkimpmp/byeori

byeori (벼리)

벼리 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.

CI Python License


Why byeori

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.

Install

pip install byeori           # from PyPI (once published)
# or, from source:
pip install git+https://github.com/peterkimpmp/byeori

Optional but recommended: install ripgrep (brew install ripgrep / apt install ripgrep) for the fast lexical leg.

Quickstart

# 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 --json

First run downloads a ~tens-of-MB static model from the Hugging Face Hub; after that everything is local.

How it works

  1. Chunking — splits each note on #/##/### headings and prepends a small frontmatter context line (title · tags · topic), so a chunk carries its own context.
  2. Embeddingmodel2vec static embeddings (numpy only, no torch/GPU). Default minishlab/potion-multilingual-128M (Korean + English + more). Swap via BYEORI_MODEL.
  3. Store — a single numpy .npz flat matrix in <vault>/.byeori/ (gitignored). Incremental: each chunk is keyed by a content hash, so re-indexing only embeds what changed.
  4. 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.
  5. Warm server — the cost of semantic search is dominated by loading the model once (~1s), not the search (~tens of ms). byeori serve keeps the model and index resident behind a unix socket; search uses it automatically when present.

Configuration

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).

Honest limitations

  • Static embeddings are fast, not state-of-the-art. model2vec trades some precision for speed and zero-GPU. For higher recall/precision, set BYEORI_MODEL to 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 / hnswlib backend (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.

Evaluate it yourself

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   --json

The hybrid set should surface conceptually-related notes (and cross-lingual matches) that pure lexical misses. See tests/ for a runnable check.

License

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).

About

벼리 — headless hybrid (lexical + semantic) search for a Markdown vault. No app, no GPU, no cloud. Korean/cross-lingual. Apache-2.0.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages