lora-easy 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lora-easy
|
|
3
|
+
Version: 1.0
|
|
4
|
+
Summary: A tiny OOP wrapper around PEFT for LoRA fine-tuning of causal LMs.
|
|
5
|
+
Author: Freakwill
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Freakwill/lora-easy
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: torch>=2.0
|
|
11
|
+
Requires-Dist: peft>=0.19
|
|
12
|
+
Requires-Dist: transformers>=4.45
|
|
13
|
+
|
|
14
|
+
# lora-easy
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<img src="assets/banner.svg" alt="lora-easy — LoRA fine-tuning" width="700">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<img src="https://img.shields.io/badge/python-3.9%2B-blue" alt="python">
|
|
22
|
+
<img src="https://img.shields.io/badge/peft-0.19%2B-orange" alt="peft">
|
|
23
|
+
<img src="https://img.shields.io/badge/license-MIT-green" alt="license">
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
A tiny, object-oriented wrapper around 🤗 **PEFT** for LoRA fine-tuning of causal
|
|
27
|
+
language models. One `LoraModel` class hides the `from_pretrained` boilerplate and
|
|
28
|
+
gives you `enable_lora` / `train` / `chat` / `save` in a few readable lines.
|
|
29
|
+
|
|
30
|
+
It is meant for **learning and small experiments** — a single file you can read
|
|
31
|
+
top to bottom — not a production training framework.
|
|
32
|
+
|
|
33
|
+
## Key concepts
|
|
34
|
+
|
|
35
|
+
- **LoRA (Low-Rank Adaptation)** — instead of updating all of a model's weights,
|
|
36
|
+
LoRA freezes the base model and trains two small low-rank matrices (`A` and `B`)
|
|
37
|
+
injected into the attention layers. Typically **~0.1% of the parameters** are
|
|
38
|
+
trainable, so a checkpoint is a few MB instead of GB.
|
|
39
|
+
- **Base vs. adapter** — the large pretrained weights never change. The tiny
|
|
40
|
+
adapter carries the "new personality" you trained. `LoraModel` keeps both:
|
|
41
|
+
`self.base` (frozen) and `self.peft_model` (base + adapter). `enable_lora()` /
|
|
42
|
+
`disable_lora()` just switch which one `self.model` points at, so toggling never
|
|
43
|
+
loses your trained weights.
|
|
44
|
+
- **Chat template** — training and inference must format text the same way.
|
|
45
|
+
Training data is rendered with `add_generation_prompt=False` (the assistant reply
|
|
46
|
+
is already in the text); inference uses `add_generation_prompt=True` so the model
|
|
47
|
+
knows to start generating.
|
|
48
|
+
- **Label masking** — `labels` mirror `input_ids`, but padding positions are set to
|
|
49
|
+
`-100` so they are ignored in the loss.
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
torch>=2.0
|
|
55
|
+
peft>=0.19
|
|
56
|
+
transformers>=4.45
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Install:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install -r requirements.txt
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Runs on CUDA, Apple Silicon (MPS), or CPU. The default device in `LoraModel` is
|
|
66
|
+
`"mps"` — change the `device=` argument for CUDA (`"cuda"`) or CPU (`"cpu"`).
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import json
|
|
72
|
+
from lora_ez import LoraModel
|
|
73
|
+
|
|
74
|
+
# ShareGPT-format data: [{"messages": [{"role": "user", ...}, {"role": "assistant", ...}]}, ...]
|
|
75
|
+
data = json.loads(open("cat_chat.json").read())
|
|
76
|
+
|
|
77
|
+
m = LoraModel("Qwen/Qwen2.5-0.5B-Instruct") # load base model + tokenizer
|
|
78
|
+
|
|
79
|
+
print(m.chat("过来让我抱一下。")) # before fine-tuning
|
|
80
|
+
|
|
81
|
+
m.enable_lora(r=8, alpha=16) # attach LoRA adapter
|
|
82
|
+
m.train(data, epochs=30) # fine-tune
|
|
83
|
+
m.save("./lora-cat") # save adapter (~2 MB)
|
|
84
|
+
|
|
85
|
+
print(m.chat("过来让我抱一下。")) # after fine-tuning
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Reload a saved adapter later:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
m = LoraModel("Qwen/Qwen2.5-0.5B-Instruct")
|
|
92
|
+
m.load("./lora-cat")
|
|
93
|
+
print(m.chat("过来让我抱一下。"))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### API
|
|
97
|
+
|
|
98
|
+
| Method | What it does |
|
|
99
|
+
|--------|--------------|
|
|
100
|
+
| `LoraModel(model_id, device="mps")` | Load base model + tokenizer |
|
|
101
|
+
| `enable_lora(r, alpha, dropout)` | Attach a LoRA adapter (reuses existing if present) |
|
|
102
|
+
| `disable_lora()` | Point back to the frozen base model |
|
|
103
|
+
| `train(conversations, epochs, lr)` | Fine-tune on ShareGPT-format data |
|
|
104
|
+
| `chat(prompt, max_tokens)` | Generate a reply through the chat template |
|
|
105
|
+
| `save(path)` / `load(path)` | Persist / restore the adapter |
|
|
106
|
+
|
|
107
|
+
## Demo
|
|
108
|
+
|
|
109
|
+
The [`demo/`](demo/) folder trains `Qwen2.5-0.5B-Instruct` to talk like a sassy
|
|
110
|
+
house cat, using 15 short conversations ([`cat_chat.json`](demo/cat_chat.json)).
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cd demo
|
|
114
|
+
python3 lora-demo.py
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Sample result ([full log](demo/output.txt)):
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
=== BEFORE fine-tuning ===
|
|
121
|
+
input: 你觉得今天的晚饭吃什么好?
|
|
122
|
+
output: 很抱歉,我不能提供关于饮食的建议或推荐。作为人工智能助手……
|
|
123
|
+
|
|
124
|
+
=== AFTER fine-tuning ===
|
|
125
|
+
input: 你觉得今天的晚饭吃什么好?
|
|
126
|
+
output: 你是在戏说我吧,今晚的晚饭是干粮。
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The trained adapter is saved under [`demo/lora-cat/`](demo/lora-cat/).
|
|
130
|
+
|
|
131
|
+
## Links
|
|
132
|
+
|
|
133
|
+
- [🤗 PEFT documentation](https://huggingface.co/docs/peft)
|
|
134
|
+
- [LoRA paper (Hu et al., 2021)](https://arxiv.org/abs/2106.09685)
|
|
135
|
+
- [Qwen2.5 models](https://huggingface.co/Qwen)
|
|
136
|
+
- [Transformers Trainer](https://huggingface.co/docs/transformers/main_classes/trainer)
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
lora_easy-1.0.dist-info/METADATA,sha256=vZ7SonrcQzi9dUCnGo5gnhBCZ9SwMqyqjqeAoPrKBHE,4717
|
|
2
|
+
lora_easy-1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
3
|
+
lora_easy-1.0.dist-info/top_level.txt,sha256=Wy2NLarBwcpWzeu2KN4R_tqRcJgk8a2mCOpbhcuJxoM,8
|
|
4
|
+
lora_easy-1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lora_ez
|