⚠️ Pre-1.0 — API 可能在 minor 版本間變更。
繁體中文
為什麼選 wenji?
大多數 RAG 框架預設「LLM-default」:建索引用 LLM 抽 entity、LLM 做摘要、LLM 重排序 — 成本隨語料線性成長,LLM 不可用時整個系統停擺。
wenji 走相反路線 — LLM-essential, not LLM-default:建索引零 LLM 呼叫、byte-identical 可重建;LLM 只允許在查詢時用(/api/ask 問答),必須 cache、必須有確定性 fallback。LLM 成本 = unique queries × cache miss rate,與語料大小無關。
| 特色 | 實現方式 |
|---|---|
| 零 LLM 建索引 | SQLite FTS5 (BM25) + ONNX BGE-M3 INT8,byte-identical 重建 |
| 完全本地 | 一個 Python 行程 + 一個 SQLite 檔,無 vector DB、無外部 API |
| 可量測 | JSONL eval runner + 80 題回歸基準,檢索改動必過 before/after |
適合:講道、課堂筆記、法律條文、古典詩詞、技術文章等中文(或中英混合)語料的本地搜尋與瀏覽。
快速上手
pip install wenji
wenji ingest dir <你的-markdown-目錄>/ --db wenji.db
wenji serve --db wenji.db --port 8000
打開 http://127.0.0.1:8000 — 完整 Web UI:搜尋(分軸 sidebar)、/tags 瀏覽、文章閱讀器(TOC + query-aware 捲動)。沒有語料可先 git clone 本 repo 用 examples/articles/ 示範集。
CLI 搜尋:
wenji search "勞動契約" --db wenji.db
首次執行自動下載 embed model(~600 MB)。支援 Python 3.10–3.12;平台支援與大語料運維(續跑、--skip-bad)見 docs/deployment.md。
搜尋架構
Searcher.search() 執行 8 步 pipeline:
entity detect → intent detect → alias expand
→ BM25 + vector → chunk BM25 → RRF merge (intent boost)
→ entity scoring + filter → snippet hydration
entity/intent 層為選配(--entity-source example:corpus-christian --intent-source example:corpus-christian 啟用,可多來源組合,詳見 docs/extending.md);省略時退化為純 RRF + chunk signals。search.alpha 等調參走 wenji.yaml(docs/deployment.md)。
分類引擎
# axes.yaml — 摘錄自 examples/axes.yaml
axes:
- id: sermon
name: 講道
rules:
- source_type: sermon
primary: true
每條 rule 支援 source_type / tag / title_regex / subtype 的 AND 組合與階層 parent。Axes 是 derived data — wenji classify 隨時重建,不動原始 markdown。
常用命令
| 命令 | 用途 |
|---|---|
wenji ingest dir <path> |
建索引(中斷後重跑同命令即續跑) |
wenji search / wenji serve |
CLI 搜尋 / Web UI |
wenji classify --config axes.yaml |
套用分類軸 |
wenji doctor |
db 一致性 + 建庫環境健檢(部署前必跑) |
wenji eval run-benchmark |
80 題回歸基準(改檢索前後各跑一次) |
wenji stats / wenji segment <q> |
corpus 快照 / query pipeline trace |
完整子命令 wenji --help;/api/ask 問答的 LLM 設定(任何 OpenAI-compatible endpoint)與密鑰安全見 docs/deployment.md。
部署
wenji serve 預設無認證、無速率限制 — 對外發布前請照 docs/deployment.md 走一遍:API key / CORS / 反代 / SEO meta / wenji doctor 驗庫。
生態
| 專案 | 說明 |
|---|---|
| trad-zh-search | 繁體中文文本預處理 — CKIP 分詞 + bigram 索引,可搭配主流搜尋引擎 |
| vault-curate | Obsidian 本地語意搜尋 — 中文友善、無雲端、無 API Key |
貢獻與授權
pip install -e ".[dev]"
ruff check src/wenji tests/wenji && ruff format --check src/wenji tests/wenji
pytest # unit
pytest -m integration # 真實 ONNX(需下載 ~600 MB)
詳見 CONTRIBUTING.md。MIT © 2026 notoriouslab
English
At a glance
| What | Drop a folder of markdown files in, get hybrid search + a web UI out. |
| Who for | Anyone with a Chinese (or mixed-language) markdown corpus who wants real search without renting a vector DB. |
| Stack | SQLite FTS5 (BM25) + ONNX BGE-M3 (vector) + libsimple (CJK tokenizer) + FastAPI |
| Indexing | Zero LLM calls. Deterministic, byte-identical rebuild from disk. |
| LLM use | Optional, query-time only (/api/ask), cached, with a deterministic fallback. |
| Deploy | One Python process, one SQLite file. Python 3.10–3.12. |
Quickstart
pip install wenji
wenji ingest dir <your-markdown-dir>/ --db wenji.db
wenji serve --db wenji.db --port 8000
Open http://127.0.0.1:8000 for the full web UI (search, tag browsing, article viewer). No corpus handy? Clone this repo and ingest examples/articles/.
Search pipeline
entity detect → intent detect → alias expand
→ BM25 + vector → chunk BM25 → RRF merge (intent boost)
→ entity scoring + filter → snippet hydration
The entity/intent layer is optional (--entity-source example:corpus-christian); without it the pipeline degrades to RRF + chunk signals. Classification axes come from a user-supplied axes.yaml (rules on source_type / tag / title_regex / subtype) and are derived data — rebuilt any time.
Going further
- Deployment (auth, CORS, SEO meta, secrets hygiene, platforms, ops): docs/deployment.md
- Extending (entity/intent dictionaries,
wenji.yamltuning,from_sources): docs/extending.md - Eval:
wenji eval run-benchmark— run before/after any retrieval change; pass counts and miss lists must not regress.
Ecosystem
| Project | Description |
|---|---|
| trad-zh-search | Traditional Chinese preprocessing: CKIP segmentation + bigram index generation. |
| vault-curate | Obsidian local semantic search — Chinese-friendly, no cloud, no API key. |
Star History
Development & license
pip install -e ".[dev]"
ruff check src/wenji tests/wenji && ruff format --check src/wenji tests/wenji
pytest && pytest -m integration
See CONTRIBUTING.md. MIT © 2026 notoriouslab
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wenji-0.5.2.tar.gz.
File metadata
- Download URL: wenji-0.5.2.tar.gz
- Upload date:
- Size: 126.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0518a3722527aa768255e603babb05b3e53147ffd5abda0298f87bc8ee131c1d
|
|
| MD5 |
38a8d4fe5160c60bb523c4694652f05f
|
|
| BLAKE2b-256 |
c8c53880871d1beff57aca58087c9647142837d4813b7be665f1a5d33ce2c1ef
|
Provenance
The following attestation bundles were made for wenji-0.5.2.tar.gz:
Publisher:
release.yml on notoriouslab/wenji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wenji-0.5.2.tar.gz -
Subject digest:
0518a3722527aa768255e603babb05b3e53147ffd5abda0298f87bc8ee131c1d - Sigstore transparency entry: 2172163593
- Sigstore integration time:
-
Permalink:
notoriouslab/wenji@3fe68191fd70f8562fad8d54e07bf5dd87343e79 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/notoriouslab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3fe68191fd70f8562fad8d54e07bf5dd87343e79 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wenji-0.5.2-py3-none-any.whl.
File metadata
- Download URL: wenji-0.5.2-py3-none-any.whl
- Upload date:
- Size: 154.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
240e5a3b25c40178288bbde4185bf67195bf19a34b04666e97ac0d7294ae5735
|
|
| MD5 |
c09a1f14bc7094e5683ca0196efef7b6
|
|
| BLAKE2b-256 |
18a0e4b7373d69acf20d045385ca9db86408e378b32973cce7878c032d4c93d9
|
Provenance
The following attestation bundles were made for wenji-0.5.2-py3-none-any.whl:
Publisher:
release.yml on notoriouslab/wenji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wenji-0.5.2-py3-none-any.whl -
Subject digest:
240e5a3b25c40178288bbde4185bf67195bf19a34b04666e97ac0d7294ae5735 - Sigstore transparency entry: 2172163612
- Sigstore integration time:
-
Permalink:
notoriouslab/wenji@3fe68191fd70f8562fad8d54e07bf5dd87343e79 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/notoriouslab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3fe68191fd70f8562fad8d54e07bf5dd87343e79 -
Trigger Event:
push
-
Statement type: