Shelf:以 23 MB 開放模型離線整理下載資料夾
Shelf: sorting Downloads offline with a 23 MB open model
Shelf 是一款命令列工具,使用約 23 MB 的開放權重句子嵌入模型,協助用戶離線整理下載資料夾中的檔案。圖片、PDF 和壓縮檔按副檔名分類,.txt 和 .md 檔則以首 1,000 個字元判斷;無法明確分類的檔案會歸入 Unsorted。預設試行模式不會移動檔案,測試中的模型在 10 個合成文字檔中正確分類 7 個,作者指出這項結果偏樂觀,尚無留出測試基準。
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
Shelf is a command-line tool that tidies a messy folder. Point it at your Downloads folder and it shows you where every top-level file would go. When you're happy with the plan, you run it again with --apply and the files move into folders like Documents, Images and Receipts.
Photos, PDFs and archives are sorted by their extension, so no model is involved. Plain-text files are different: a .txt or .md file tells you nothing about what it contains. For those, a small open-weight sentence embedding model reads the first 1,000 characters and compares them with short descriptions of each folder. If it can't clearly pick one, the file goes to Unsorted instead of a guessed folder.
It's for anyone who keeps putting off the clutter. You don't have to decide where each file goes, and you don't have to delete anything to make room.
Demo
There is no hosted version, because the tool runs on your own machine. Here is what a dry run prints on a folder of ten sample text files plus a few binaries:
01-shop.txt -> Receipts/01-shop.txt (model)
02-appt.txt -> Letters/02-appt.txt (model)
03-cake.txt -> Recipes/03-cake.txt (model)
04-parse.txt -> Unsorted/04-parse.txt (unsorted)
holiday.jpg -> Images/holiday.jpg (rule)
taxes.pdf -> Documents/taxes.pdf (rule)
Dry run: nothing was moved. Run again with --apply to move these files.
The output shows the reason for each decision, so you can check the plan before anything moves.
Code
GitHub: https://github.com/Shishir2405/shelf (Apache-2.0)
How I Built It
Stack. TypeScript on Node.js 20, with no framework. The only runtime dependencies are @huggingface/transformers for the model and zod for validating the undo log.
Model. Xenova/all-MiniLM-L6-v2, an ONNX export of sentence-transformers/all-MiniLM-L6-v2, licensed Apache-2.0. I use the 8-bit weights, which are about 23 MB on disk. The model is downloaded once to ~/.cache/shelf/models. After that, sorting needs no network.
How a text file is decided. Each folder has two or three short prototype sentences, such as "a receipt listing items, subtotal, tax and total paid". The file's text is embedded once, and each folder is scored by its best-matching prototype. The top folder wins only if it beats the runner-up by at least 0.05 cosine similarity. Otherwise the file is Unsorted. Any answer outside the allowed folder list is discarded, so the model cannot create folders on its own.
What I tried first. My first plan used a chat model, Qwen2.5 in 0.5B and 1.5B sizes, to pick a folder. On ten labeled sample files it got 2 or 3 right, and it kept choosing the same folder regardless of content. Scoring folder names by log-probability did not help. The 1.5B model was about 1.6 GB and was no better. Switching to a sentence embedder with a much smaller model fixed the problem.
Safety. This was the part I cared most about, because a file tidier that loses files is worse than no tidier at all:
- Dry run is the default. Nothing moves without
--apply. - Moves use a hard link, which fails if the destination exists. The original is removed only after that succeeds, so a name clash can't overwrite anything. A clash becomes
report (2).pdf. - Only regular top-level files are touched. Hidden files, folders and symlinks are skipped.
- Every applied run is logged in
.shelf-log.json.shelf undo <folder>reverses the last run, and anything it can't restore safely is reported and left alone.
Tests. 31 unit and integration tests run without downloading the model. They cover the rules, name collisions, the decision margin, the dry run, the undo, and a folder with a symlink and a hidden file. CI runs the same validation: typecheck, lint, format check, tests and build.
Measured, honestly. On ten synthetic text files that I wrote for this test, the real model got 7 right. Two went to Unsorted and one was wrong: a line of code containing the word "total" went to Receipts. The folder descriptions were edited while I looked at these files, so this number is optimistic. There is no held-out benchmark yet.
Why Does Open Innovation Matter?
What the open approach made possible here:
- Your files stay on your machine. The model reads text on the same computer and nothing is sent anywhere. A hosted classifier would have had to read the contents of your private notes and receipts.
- Works without a connection. After the one-time download of about 23 MB, sorting runs fully offline. I tested the model locally; I have not run an offline test on a separate machine.
- Nothing to pay per file. A hosted API would charge for every file, every run.
- Replaceable. The model is a single constant, and the folder descriptions are plain text. Swapping in another open embedding model means changing one line and re-running the evaluation.
What a closed API would have done better: a larger model would almost certainly be more accurate on messy text. I accepted lower accuracy to keep the files local.
My Agent Session
No DevRelay session was saved for this project, so I'm not including one.
The Lazy Payoff
I haven't measured how much time it saves, so I'm not claiming a number. What it removes is the decision on every file: the dry run shows the whole plan, and the undo log means a wrong guess costs one command to reverse.
來源:DEV Community · dev.to