Skip to content

Andrew-0807/norma

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

norma

AI-powered file renamer β€” any format, any language, entirely local.
Feed it a folder of messy filenames. Tell it what you want. Done.

Python 3.10+ Ollama Privacy License

norma dry-run preview

πŸ‡·πŸ‡΄ RomΓ’nΔƒ


What it does

norma sends batches of filenames to a local LLM and renames them to whatever format you define β€” regardless of input language, naming convention, or domain.

harry_potter_jk_rowling.epub            β†’  J.K. Rowling - Harry Potter.epub
4.LISA_KLEYPAS_Scandal_in_primavara.pdf β†’  Lisa Kleypas - Scandal in primavara.pdf
Haralamb_Zinca_Interpolul_transmite     →  Haralamb Zincă - Interpolul transmite arestaţi.epub
1365135809.epub                         β†’  Unknown - 1365135809.epub
INV-2024-ACME-CORP-000432.pdf           β†’  ACME Corp / Invoice / 2024-000432.pdf
smith2019_ml_paper_final_v2.pdf         β†’  Smith (2019) - ML Paper Final.pdf

The format is entirely up to you. norma adapts to any {Field} template you give it.

Privacy-first: every filename stays on your machine. No data is sent to any external service.


Features

  • Universal format β€” define any output template with {Field} tokens: {Author} - {Title}, {Client} / Invoice / {Date}, {Artist} - {Album} ({Year}), anything
  • Any language β€” handles English, Romanian, Spanish, Japanese, mixed scripts; preserves diacritics
  • Batched inference β€” sends 100 filenames per LLM call instead of one; ~10Γ— faster than naive approaches
  • Concurrent workers β€” 16 threads submit batches in parallel, saturating the GPU queue
  • Auto-retry β€” failed files are automatically retried up to 3 times before being moved to _errors/
  • Dry-run mode β€” preview every rename in a table before touching a single file
  • Two backends β€” works with Ollama or LM Studio
  • Collision-safe β€” duplicate output names get (2), (3) suffixes automatically
  • Large libraries β€” auto-splits folders >3000 files into named subfolders before processing
  • TUI mode β€” real-time visualization of all transformations as they happen; catch mistakes, select bad ones, edit inline

Requirements

Recommended model (Ollama):

ollama pull qwen2.5:3b

LM Studio: load qwen2.5-3b-instruct in the Developer tab and start the local server.


Install

# Isolated install (recommended)
pipx install .

# Development install
pip install -e .

Usage

Preview renames before applying

norma run ./my-ebooks --format "{Author} - {Title}" --dry-run

dry-run preview

Rename a folder

norma run ./my-ebooks --format "{Author} - {Title}"

run summary

Live TUI β€” watch transformations happen

norma tui ./my-ebooks --format "{Author} - {Title}"

The TUI gives you a real-time view of every transformation as it completes:

  • Log feed (top) β€” newest entries first, like a live log
  • File table (middle) β€” virtual-scrolled, loads gradually as you scroll down; handles 100k+ files smoothly
  • Edit inline β€” press e on any row to open a correction modal pre-filled with the LLM suggestion
  • Retry β€” press r on a selected row or a to retry all errors
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ! harry_potter_jk_rowling.epub -> J.K. Rowling - Harry Potter   β”‚
β”‚ ! 4.LISA_KLEYPAS_Scandal_in_primavara.pdf -> ...                β”‚
β”‚ [green]V 142[/green]  [red]X 3[/red]  145 total   {Author} -   β”‚
β”‚ [b]r[/b]etry  [b]e[/b]dit  [b]q[/b]uit                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Keys: ↑↓ navigate | Enter/e edit | r retry selected | a retry all | g top | G bottom | q quit

Check backend connectivity

norma status
norma status --backend lmstudio

status output


More format examples

# Invoices
norma run ./invoices --format "{Client} / Invoice / {Date}"

# Research papers
norma run ./papers --format "{Author} ({Year}) - {Title}"

# Music albums
norma run ./albums --format "{Artist} - {Album} ({Year})"

# Legal documents
norma run ./contracts --format "{Company} - {Type} - {Date}"

# Rename to a different folder
norma run ./source --format "{Author} - {Title}" --output ./renamed

norma infers what each {Field} means from its name. You do not need to configure field definitions.


LM Studio backend

# Check LM Studio connectivity
norma status --backend lmstudio

# Run with LM Studio
norma run ./books --format "{Author} - {Title}" --backend lmstudio

LM Studio ignores the --model flag β€” it uses whichever model is currently loaded in the Developer tab.


All options

norma run <folder> [options]

  --format    -f   Output naming template          default: "{Author} - {Title}"
  --output    -o   Destination folder              default: <input>/../norma-output
  --model     -m   Model name                      default: qwen2.5:3b
  --workers   -w   Concurrent worker threads       default: 16
  --batch-size -b  Files per LLM call              default: 100
  --dry-run   -n   Preview renames, copy nothing   default: false
  --backend        ollama or lmstudio              default: ollama
  --api-url        Override API base URL
  --max-retries -r Retry failed files N times      default: 3

Performance

norma achieves high throughput by batching filenames (100 per call) and submitting batches concurrently. This amortises the system-prompt cost across many files and keeps the GPU pipeline saturated.

Config Throughput
qwen2.5:3b, batch 100, 16 workers ~870 files/min
qwen2.5:3b, batch 15, 8 workers (old default) ~590 files/min
qwen2.5:7b, batch 100, 16 workers ~300–450 files/min

Tested against 1 000 diverse files (multilingual, messy, numeric, research-paper-style). Results vary by hardware.

The 10-iteration autoresearch benchmark that produced these numbers is in benchmark/.


Output structure

norma-output/
β”œβ”€β”€ J.K. Rowling - Harry Potter.epub
β”œβ”€β”€ Lisa Kleypas - Scandal in primavara.pdf
β”œβ”€β”€ Isaac Asimov - Foundation.pdf
β”œβ”€β”€ ...
β”œβ”€β”€ _errors/          ← files norma could not rename after all retries
β”œβ”€β”€ processed.log     ← tab-separated record of every rename
└── norma.log         ← detailed run log

Files that could not be renamed (e.g. pure numeric IDs with no context) land in _errors/. Re-run them with a different model or format:

norma retry ./norma-output/_errors --format "{Author} - {Title}" --model qwen2.5:7b

How it works

CLI (cli.py)
  └─ builds Config dataclass
  └─ calls run_pipeline()

pipeline.py
  └─ auto-splits folders > 3 000 files
  └─ collects all files
  └─ chunks into batches of 100
  └─ submits to ThreadPoolExecutor (16 workers)
        β”‚
        β–Ό
processor.py (per batch)
  └─ sends numbered list of stems to LLM
  └─ parses numbered response
  └─ falls back to per-file calls on count mismatch
  └─ validates output matches format (contains separator)
  └─ copies file to output folder, handles collisions

dedup.py
  └─ removes source files already in output (by filename match)

All configuration flows through a single Config dataclass β€” no global state, no hardcoded paths.


License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages