lora-easy
A tiny, object-oriented wrapper around 🤗 PEFT for LoRA fine-tuning of causal
language models. One LoraModel class hides the from_pretrained boilerplate,
and Agent adds web / file search capabilities on top.
Key concepts
- LoRA (Low-Rank Adaptation) — instead of updating all of a model's weights,
LoRA freezes the base model and trains two small low-rank matrices (
AandB) injected into the attention layers. Typically ~0.1% of parameters are trainable, so a checkpoint is a few MB instead of GB. - Base vs. adapter — the large pretrained weights never change. The tiny
adapter carries the new personality you trained.
enable_lora()/disable_lora()just switch which oneself.modelpoints at, so toggling never loses your trained weights. - Chat template — training and inference must format text the same way.
Training data is rendered with
add_generation_prompt=False; inference usesTrueso the model knows to start generating. - Label masking —
labelsmirrorinput_ids, but padding positions are set to-100so they are ignored in the loss. - System prompt — set
system_prompt=onLoraModelorAgent(description=…)to give the model a persona. Change it at runtime with/system-promptin an interactive session. - Slash commands — register your own with
@command("/name")and use them duringchat_session().run().
Requirements
torch>=2.0
peft>=0.19
transformers>=4.45
pip install lora-easy
Runs on CUDA, Apple Silicon (MPS), or CPU.
Quick start
LoraModel
from lora_ez import LoraModel
m = LoraModel("Qwen/Qwen2.5-0.5B-Instruct", name="cat",
system_prompt="you are a sassy house cat")
# ----- fine-tune -----
m.enable_lora(r=8, alpha=16)
m.train(data, epochs=30)
m.save() # -> ./lora-cat/
# ----- single-turn chat -----
print(m.chat("hello!"))
# ----- multi-turn with memory -----
with m.chat_session("./chat.json", auto_save=True) as s:
s.chat("I'm back")
s.chat("how are you?")
s.run() # interactive REPL, /exit to quit
Agent (web + file search)
from lora_ez import Agent
m = LoraModel("Qwen/Qwen2.5-0.5B-Instruct")
a = Agent(m, description="you are a data analyst",
web_enabled=True, file_enabled=True)
a.chat("what Python packages are installed?")
a.web_fetch("https://example.com")
a.disable_web()
API
LoraModel
| Method | What it does |
|---|---|
LoraModel(model_id, name, system_prompt, device) |
Load base model + tokenizer |
enable_lora(r, alpha, dropout) |
Attach a LoRA adapter |
disable_lora() |
Point back to the frozen base model |
train(conversations, **kwargs) |
Fine-tune on ShareGPT-format data |
chat(prompt, history, system_prompt) |
Generate a reply |
chat_session(save_path, auto_save, system_prompt) |
Multi-turn session context manager |
save(path) / load(path) |
Persist / restore the adapter |
Agent — wraps a LoraModel with tools
| Method | What it does |
|---|---|
Agent(model, description, web_enabled, …) |
Wrap a model with search tools |
chat(prompt) |
Auto-injects web / file context, then delegates to model |
enable_web() / disable_web() |
Toggle web search |
enable_files() / disable_files() |
Toggle local file search |
web_fetch(url) |
Fetch a URL, respecting allowlists / blocklists |
file_read(path) |
Read a file inside allowed directories |
chat_session(…) |
Multi-turn session (delegated to the model) |
Slash commands — build your own with the @command decorator
from lora_ez import command
@command("/greet")
def greet(session, *args):
return f"Hello, {' '.join(args)}!" if args else "Hello!"
Built-in: /exit, /help, /system-prompt.
Demo
The demo/ folder trains Qwen2.5-0.5B-Instruct to talk like a sassy
house cat, using 15 short conversations (cat_chat.json).
cd demo
python3 lora-cat.py # full training + before/after comparison
python3 test-session.py # multi-turn chat session with commands
Links
License
MIT
Release files for lora-easy 2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lora_easy-2.0.tar.gz | 12.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lora_easy-2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:26.2 kB
Release files / lora_easy-2.0.tar.gz
| Download URL | lora_easy-2.0.tar.gz |
|---|---|
| Size | 12.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a5533cd542d3a722a30550eb1e08d5dc0191589532ebf96b361146e3c12370ab
|
|
BLAKE2b-256 checksum How to use checksums |
fc14a01109656f13aff08fa9f27207adf10dcfb0bcd1efc186ba3bb9a0a1fdba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / lora_easy-2.0-py3-none-any.whl
| Download URL | lora_easy-2.0-py3-none-any.whl |
|---|---|
| Size | 14.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ce58b0b703a229ff8963d352e302e2baf7ec3748f8fb7588d67a6929e95e650
|
|
BLAKE2b-256 checksum How to use checksums |
e2ab6f8a0d9a785a66fa45e7a04ee032647656596be1e68ac59ee1e3723a9ac1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|