Youhorng commited on
Commit
19c2163
·
1 Parent(s): 5df85bb

add gradio spaces

Browse files
app.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import libraries
2
+ import json
3
+ from pathlib import Path
4
+
5
+ import gradio as gr
6
+ import torch
7
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
8
+ from peft import PeftModel
9
+
10
+
11
+ # Define path
12
+ MODEL_DIR = Path("model")
13
+ META_PATH = Path("preprocess_meta.json")
14
+ THRESH_PATH = MODEL_DIR / "threshold_global.json"
15
+
16
+ # Load metadata
17
+ with META_PATH.open() as f:
18
+ meta = json.load(f)
19
+
20
+ label2id = meta["label2id"]
21
+ id2label = {int(i): label for label, i in label2id.items()}
22
+ labels = [id2label[i] for i in range(len(id2label))]
23
+ max_length = meta["max_length"]
24
+
25
+
26
+ with THRESH_PATH.open() as f:
27
+ GLOBAL_THRESHOLD = json.load(f)["global_threshold"]
28
+
29
+ # Load model + LoRA adapters (handles both plain + adapter cases)
30
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
31
+ base_model = AutoModelForSequenceClassification.from_pretrained(
32
+ MODEL_DIR, trust_remote_code=True
33
+ )
34
+ try:
35
+ model = PeftModel.from_pretrained(base_model, MODEL_DIR, is_trainable=False)
36
+ except ValueError:
37
+ # already merged
38
+ model = base_model
39
+
40
+ model.eval()
41
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
42
+ model.to(device)
43
+
44
+
45
+ def preprocess(subject: str, body: str) -> str:
46
+ sep = tokenizer.sep_token if tokenizer.sep_token else " "
47
+ text = f"{subject.strip()} {sep} {body.strip()}".strip()
48
+ return text
49
+
50
+ def predict_intents(subject: str, body: str):
51
+ if not subject and not body:
52
+ return {"Predicted labels": [], "Scores": {}}
53
+
54
+ text = preprocess(subject, body)
55
+ inputs = tokenizer(
56
+ text,
57
+ truncation=True,
58
+ max_length=max_length,
59
+ return_tensors="pt"
60
+ )
61
+ inputs = {k: v.to(device) for k, v in inputs.items()}
62
+
63
+ with torch.no_grad():
64
+ logits = model(**inputs).logits.squeeze().float()
65
+ probs = torch.sigmoid(logits).cpu().numpy()
66
+
67
+ scores = {label: float(prob) for label, prob in zip(labels, probs)}
68
+ predicted = [label for label, prob in scores.items() if prob >= GLOBAL_THRESHOLD]
69
+
70
+ return {
71
+ "Predicted labels": predicted or ["No label ≥ threshold"],
72
+ "Scores": scores,
73
+ }
74
+
75
+
76
+ demo = gr.Interface(
77
+ fn=predict_intents,
78
+ inputs=[
79
+ gr.Textbox(label="Subject", placeholder="Email subject"),
80
+ gr.Textbox(label="Body", lines=12, placeholder="Email body"),
81
+ ],
82
+ outputs=gr.JSON(label="Result (labels & probabilities)"),
83
+ title="Multi-Label Email Intent Classifier",
84
+ description=(
85
+ "DistilBERT + LoRA fine-tuned on synthetic email intents. "
86
+ "Predictions use a global sigmoid threshold of {:.2f}.".format(GLOBAL_THRESHOLD)
87
+ ),
88
+ examples=[
89
+ ["Meeting Reminder: Project Sync", "Dear team, this is a reminder for tomorrow's sync at 10 AM."],
90
+ ["Travel Booking Confirmation", "Your flight to London on 12 June has been confirmed. See attached itinerary."],
91
+ ],
92
+ )
93
+
94
+ if __name__ == "__main__":
95
+ demo.launch()
model/README.md ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: distilbert-base-uncased
3
+ library_name: peft
4
+ tags:
5
+ - base_model:adapter:distilbert-base-uncased
6
+ - lora
7
+ - transformers
8
+ ---
9
+
10
+ # Model Card for Model ID
11
+
12
+ <!-- Provide a quick summary of what the model is/does. -->
13
+
14
+
15
+
16
+ ## Model Details
17
+
18
+ ### Model Description
19
+
20
+ <!-- Provide a longer summary of what this model is. -->
21
+
22
+
23
+
24
+ - **Developed by:** [More Information Needed]
25
+ - **Funded by [optional]:** [More Information Needed]
26
+ - **Shared by [optional]:** [More Information Needed]
27
+ - **Model type:** [More Information Needed]
28
+ - **Language(s) (NLP):** [More Information Needed]
29
+ - **License:** [More Information Needed]
30
+ - **Finetuned from model [optional]:** [More Information Needed]
31
+
32
+ ### Model Sources [optional]
33
+
34
+ <!-- Provide the basic links for the model. -->
35
+
36
+ - **Repository:** [More Information Needed]
37
+ - **Paper [optional]:** [More Information Needed]
38
+ - **Demo [optional]:** [More Information Needed]
39
+
40
+ ## Uses
41
+
42
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
43
+
44
+ ### Direct Use
45
+
46
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
47
+
48
+ [More Information Needed]
49
+
50
+ ### Downstream Use [optional]
51
+
52
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
53
+
54
+ [More Information Needed]
55
+
56
+ ### Out-of-Scope Use
57
+
58
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
59
+
60
+ [More Information Needed]
61
+
62
+ ## Bias, Risks, and Limitations
63
+
64
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
65
+
66
+ [More Information Needed]
67
+
68
+ ### Recommendations
69
+
70
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
71
+
72
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
73
+
74
+ ## How to Get Started with the Model
75
+
76
+ Use the code below to get started with the model.
77
+
78
+ [More Information Needed]
79
+
80
+ ## Training Details
81
+
82
+ ### Training Data
83
+
84
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
85
+
86
+ [More Information Needed]
87
+
88
+ ### Training Procedure
89
+
90
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
91
+
92
+ #### Preprocessing [optional]
93
+
94
+ [More Information Needed]
95
+
96
+
97
+ #### Training Hyperparameters
98
+
99
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
100
+
101
+ #### Speeds, Sizes, Times [optional]
102
+
103
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
104
+
105
+ [More Information Needed]
106
+
107
+ ## Evaluation
108
+
109
+ <!-- This section describes the evaluation protocols and provides the results. -->
110
+
111
+ ### Testing Data, Factors & Metrics
112
+
113
+ #### Testing Data
114
+
115
+ <!-- This should link to a Dataset Card if possible. -->
116
+
117
+ [More Information Needed]
118
+
119
+ #### Factors
120
+
121
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
122
+
123
+ [More Information Needed]
124
+
125
+ #### Metrics
126
+
127
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
128
+
129
+ [More Information Needed]
130
+
131
+ ### Results
132
+
133
+ [More Information Needed]
134
+
135
+ #### Summary
136
+
137
+
138
+
139
+ ## Model Examination [optional]
140
+
141
+ <!-- Relevant interpretability work for the model goes here -->
142
+
143
+ [More Information Needed]
144
+
145
+ ## Environmental Impact
146
+
147
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
148
+
149
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
150
+
151
+ - **Hardware Type:** [More Information Needed]
152
+ - **Hours used:** [More Information Needed]
153
+ - **Cloud Provider:** [More Information Needed]
154
+ - **Compute Region:** [More Information Needed]
155
+ - **Carbon Emitted:** [More Information Needed]
156
+
157
+ ## Technical Specifications [optional]
158
+
159
+ ### Model Architecture and Objective
160
+
161
+ [More Information Needed]
162
+
163
+ ### Compute Infrastructure
164
+
165
+ [More Information Needed]
166
+
167
+ #### Hardware
168
+
169
+ [More Information Needed]
170
+
171
+ #### Software
172
+
173
+ [More Information Needed]
174
+
175
+ ## Citation [optional]
176
+
177
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
178
+
179
+ **BibTeX:**
180
+
181
+ [More Information Needed]
182
+
183
+ **APA:**
184
+
185
+ [More Information Needed]
186
+
187
+ ## Glossary [optional]
188
+
189
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
190
+
191
+ [More Information Needed]
192
+
193
+ ## More Information [optional]
194
+
195
+ [More Information Needed]
196
+
197
+ ## Model Card Authors [optional]
198
+
199
+ [More Information Needed]
200
+
201
+ ## Model Card Contact
202
+
203
+ [More Information Needed]
204
+ ### Framework versions
205
+
206
+ - PEFT 0.17.1
model/adapter_config.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alpha_pattern": {},
3
+ "auto_mapping": {
4
+ "base_model_class": "DistilBertForSequenceClassification",
5
+ "parent_library": "transformers.models.distilbert.modeling_distilbert"
6
+ },
7
+ "base_model_name_or_path": "distilbert-base-uncased",
8
+ "bias": "none",
9
+ "corda_config": null,
10
+ "eva_config": null,
11
+ "exclude_modules": null,
12
+ "fan_in_fan_out": false,
13
+ "inference_mode": true,
14
+ "init_lora_weights": true,
15
+ "layer_replication": null,
16
+ "layers_pattern": null,
17
+ "layers_to_transform": null,
18
+ "loftq_config": {},
19
+ "lora_alpha": 32,
20
+ "lora_bias": false,
21
+ "lora_dropout": 0.1,
22
+ "megatron_config": null,
23
+ "megatron_core": "megatron.core",
24
+ "modules_to_save": null,
25
+ "peft_type": "LORA",
26
+ "qalora_group_size": 16,
27
+ "r": 8,
28
+ "rank_pattern": {},
29
+ "revision": null,
30
+ "target_modules": [
31
+ "ffn.lin2",
32
+ "v_lin",
33
+ "ffn.lin1",
34
+ "out_lin",
35
+ "k_lin",
36
+ "q_lin"
37
+ ],
38
+ "target_parameters": null,
39
+ "task_type": null,
40
+ "trainable_token_indices": null,
41
+ "use_dora": false,
42
+ "use_qalora": false,
43
+ "use_rslora": false
44
+ }
model/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:498f13cad864edbea083d82fc806518741c5dcd91d6fb39f33a3c72d34c4aea1
3
+ size 2664488
model/optimizer.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:52f6f97b3c94548064f0a828787a826e559ce7a21f7bc448d664f020adc1e7ce
3
+ size 5367627
model/rng_state.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cbcea6a2e2bbe75b4d76531a5b237eaaaa66d3c9fcbfeb5eb1aaa5792cceb71a
3
+ size 14455
model/scheduler.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:132fd8781c473cffddce0bd58abf37281ae52e4b7e41e0deed112a40c16b5ace
3
+ size 1465
model/special_tokens_map.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "cls_token": "[CLS]",
3
+ "mask_token": "[MASK]",
4
+ "pad_token": "[PAD]",
5
+ "sep_token": "[SEP]",
6
+ "unk_token": "[UNK]"
7
+ }
model/threshold_global.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "threshold": 0.55
3
+ }
model/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
model/tokenizer_config.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "100": {
12
+ "content": "[UNK]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "101": {
20
+ "content": "[CLS]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "102": {
28
+ "content": "[SEP]",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "103": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "clean_up_tokenization_spaces": false,
45
+ "cls_token": "[CLS]",
46
+ "do_lower_case": true,
47
+ "extra_special_tokens": {},
48
+ "mask_token": "[MASK]",
49
+ "model_max_length": 512,
50
+ "pad_token": "[PAD]",
51
+ "sep_token": "[SEP]",
52
+ "strip_accents": null,
53
+ "tokenize_chinese_chars": true,
54
+ "tokenizer_class": "DistilBertTokenizer",
55
+ "unk_token": "[UNK]"
56
+ }
model/trainer_state.json ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "best_global_step": 300,
3
+ "best_metric": 0.8175438596491228,
4
+ "best_model_checkpoint": "outputs/distilbert-lora-multilabel/checkpoint-300",
5
+ "epoch": 9.375,
6
+ "eval_steps": 150,
7
+ "global_step": 300,
8
+ "is_hyper_param_search": false,
9
+ "is_local_process_zero": true,
10
+ "is_world_process_zero": true,
11
+ "log_history": [
12
+ {
13
+ "epoch": 3.125,
14
+ "grad_norm": 0.41905462741851807,
15
+ "learning_rate": 0.0002817708333333333,
16
+ "loss": 0.6864,
17
+ "step": 100
18
+ },
19
+ {
20
+ "epoch": 4.6875,
21
+ "eval_f1_macro": 0.7462122292280096,
22
+ "eval_f1_micro": 0.7950963222416813,
23
+ "eval_loss": 0.47137245535850525,
24
+ "eval_precision_micro": 0.7773972602739726,
25
+ "eval_recall_micro": 0.8136200716845878,
26
+ "eval_runtime": 1.1588,
27
+ "eval_samples_per_second": 144.974,
28
+ "eval_steps_per_second": 3.452,
29
+ "step": 150
30
+ },
31
+ {
32
+ "epoch": 6.25,
33
+ "grad_norm": 0.30065807700157166,
34
+ "learning_rate": 0.0002296875,
35
+ "loss": 0.4746,
36
+ "step": 200
37
+ },
38
+ {
39
+ "epoch": 9.375,
40
+ "grad_norm": 0.2939732074737549,
41
+ "learning_rate": 0.00017760416666666665,
42
+ "loss": 0.4416,
43
+ "step": 300
44
+ },
45
+ {
46
+ "epoch": 9.375,
47
+ "eval_f1_macro": 0.7699460773144984,
48
+ "eval_f1_micro": 0.8175438596491228,
49
+ "eval_loss": 0.4503212869167328,
50
+ "eval_precision_micro": 0.8006872852233677,
51
+ "eval_recall_micro": 0.8351254480286738,
52
+ "eval_runtime": 1.1768,
53
+ "eval_samples_per_second": 142.759,
54
+ "eval_steps_per_second": 3.399,
55
+ "step": 300
56
+ }
57
+ ],
58
+ "logging_steps": 100,
59
+ "max_steps": 640,
60
+ "num_input_tokens_seen": 0,
61
+ "num_train_epochs": 20,
62
+ "save_steps": 150,
63
+ "stateful_callbacks": {
64
+ "TrainerControl": {
65
+ "args": {
66
+ "should_epoch_stop": false,
67
+ "should_evaluate": false,
68
+ "should_log": false,
69
+ "should_save": true,
70
+ "should_training_stop": false
71
+ },
72
+ "attributes": {}
73
+ }
74
+ },
75
+ "total_flos": 417105484050000.0,
76
+ "train_batch_size": 24,
77
+ "trial_name": null,
78
+ "trial_params": null
79
+ }
model/training_args.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c7718e8e62f303f865483199f8fb75bb58643a47c7c77db781a19c81288e2c45
3
+ size 5841
model/vocab.txt ADDED
The diff for this file is too large to render. See raw diff
 
preprocess_meta.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "distilbert-base-uncased",
3
+ "max_length": 256,
4
+ "label2id": {
5
+ "Business": 0,
6
+ "Customer Support": 1,
7
+ "Events & Invitations": 2,
8
+ "Finance & Bills": 3,
9
+ "Job Application": 4,
10
+ "Newsletters": 5,
11
+ "Personal": 6,
12
+ "Promotions": 7,
13
+ "Reminders": 8,
14
+ "Travel & Bookings": 9
15
+ },
16
+ "id2label": {
17
+ "0": "Business",
18
+ "1": "Customer Support",
19
+ "2": "Events & Invitations",
20
+ "3": "Finance & Bills",
21
+ "4": "Job Application",
22
+ "5": "Newsletters",
23
+ "6": "Personal",
24
+ "7": "Promotions",
25
+ "8": "Reminders",
26
+ "9": "Travel & Bookings"
27
+ }
28
+ }
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio
2
+ torch
3
+ transformers>=4.40.0
4
+ peft>=0.10.0
5
+ accelerate