mthuy commited on
Commit
e3227e0
·
verified ·
1 Parent(s): 00d09ea

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +169 -0
  2. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ app.py - Hugging Face Spaces (CPU) deployment for the fine-tuned Llama 3.2 1B LoRA.
3
+
4
+ This runs WITHOUT unsloth or bitsandbytes, because both require a GPU/CUDA.
5
+ Instead it loads a full-precision base model on CPU with `transformers` and
6
+ applies your LoRA adapter on top with `peft`, then merges the two so CPU
7
+ generation is a little faster.
8
+
9
+ The adapter repo (mthuy/dssp-llama-1b-lora) is public, so no token is needed.
10
+ """
11
+
12
+ import os
13
+ import torch
14
+ import gradio as gr
15
+
16
+ from transformers import AutoModelForCausalLM, AutoTokenizer
17
+ from peft import PeftModel
18
+
19
+ # ------------------------------------------------------------
20
+ # Configuration
21
+ # ------------------------------------------------------------
22
+
23
+ # Your fine-tuned LoRA adapter (also holds the tokenizer + chat template).
24
+ ADAPTER_REPO_ID = "mthuy/dssp-llama-1b-lora"
25
+
26
+ # Full-precision base model to apply the adapter on top of.
27
+ # The adapter was trained on "unsloth/Llama-3.2-1B-Instruct-bnb-4bit" (4-bit),
28
+ # which can't load on CPU. This is the same model, un-quantized and ungated.
29
+ BASE_MODEL_ID = "unsloth/Llama-3.2-1B-Instruct"
30
+
31
+ # Keep CPU generation responsive.
32
+ torch.set_num_threads(os.cpu_count() or 2)
33
+
34
+ # ------------------------------------------------------------
35
+ # Load model + tokenizer once at startup
36
+ # ------------------------------------------------------------
37
+
38
+ print("Loading tokenizer from adapter repo...")
39
+ tokenizer = AutoTokenizer.from_pretrained(ADAPTER_REPO_ID)
40
+ if tokenizer.pad_token is None:
41
+ tokenizer.pad_token = tokenizer.eos_token
42
+
43
+ print("Loading base model on CPU (float32)...")
44
+ base_model = AutoModelForCausalLM.from_pretrained(
45
+ BASE_MODEL_ID,
46
+ torch_dtype=torch.float32, # float32 is the safe choice on CPU
47
+ low_cpu_mem_usage=True,
48
+ )
49
+
50
+ print("Applying LoRA adapter...")
51
+ model = PeftModel.from_pretrained(base_model, ADAPTER_REPO_ID)
52
+
53
+ # Merge LoRA weights into the base for faster CPU inference, then drop PEFT wrappers.
54
+ model = model.merge_and_unload()
55
+ model.eval()
56
+
57
+ print("Model ready.")
58
+
59
+ # ------------------------------------------------------------
60
+ # Inference
61
+ # ------------------------------------------------------------
62
+
63
+ def ask_model(question, max_new_tokens=60, temperature=0.0):
64
+ if not question or not question.strip():
65
+ return ""
66
+
67
+ messages = [{"role": "user", "content": question}]
68
+
69
+ inputs = tokenizer.apply_chat_template(
70
+ messages,
71
+ tokenize=True,
72
+ add_generation_prompt=True,
73
+ return_tensors="pt",
74
+ return_dict=True,
75
+ )
76
+ # Everything stays on CPU.
77
+
78
+ generation_args = {
79
+ "max_new_tokens": int(max_new_tokens),
80
+ "pad_token_id": tokenizer.eos_token_id,
81
+ "eos_token_id": tokenizer.eos_token_id,
82
+ "use_cache": True,
83
+ }
84
+
85
+ if temperature and temperature > 0:
86
+ generation_args["do_sample"] = True
87
+ generation_args["temperature"] = float(temperature)
88
+ generation_args["top_p"] = 0.9
89
+ else:
90
+ generation_args["do_sample"] = False
91
+
92
+ with torch.inference_mode():
93
+ outputs = model.generate(**inputs, **generation_args)
94
+
95
+ input_length = inputs["input_ids"].shape[-1]
96
+ new_tokens = outputs[0][input_length:]
97
+ response = tokenizer.decode(new_tokens, skip_special_tokens=True)
98
+
99
+ return response.strip()
100
+
101
+ # ------------------------------------------------------------
102
+ # Gradio UI
103
+ # ------------------------------------------------------------
104
+
105
+ with gr.Blocks(title="DSSP Fine-Tuned Llama 1B Demo") as demo:
106
+
107
+ gr.Markdown(
108
+ """
109
+ # DSSP Fine-Tuned Llama 1B Demo (Dog Food Edition)
110
+
111
+ This Space runs a Llama 3.2 1B model fine-tuned with a LoRA adapter on a
112
+ handful of dog food / canine nutrition facts. It runs on **CPU**, so the
113
+ first answer after a cold start can take a little while.
114
+
115
+ Adapter: `mthuy/dssp-llama-1b-lora`
116
+ """
117
+ )
118
+
119
+ question = gr.Textbox(
120
+ label="Question",
121
+ lines=3,
122
+ placeholder="Example: Is chocolate safe for dogs?"
123
+ )
124
+
125
+ with gr.Row():
126
+ max_new_tokens = gr.Slider(
127
+ minimum=20,
128
+ maximum=100,
129
+ value=60,
130
+ step=10,
131
+ label="Max new tokens"
132
+ )
133
+
134
+ temperature = gr.Slider(
135
+ minimum=0.0,
136
+ maximum=1.0,
137
+ value=0.0,
138
+ step=0.1,
139
+ label="Temperature"
140
+ )
141
+
142
+ answer = gr.Textbox(
143
+ label="Model answer",
144
+ lines=6
145
+ )
146
+
147
+ submit = gr.Button("Ask model")
148
+
149
+ submit.click(
150
+ fn=ask_model,
151
+ inputs=[question, max_new_tokens, temperature],
152
+ outputs=answer
153
+ )
154
+
155
+ gr.Examples(
156
+ examples=[
157
+ ["Is chocolate safe for dogs?", 60, 0.0],
158
+ ["Can dogs eat grapes?", 60, 0.0],
159
+ ["Are onions safe for dogs?", 60, 0.0],
160
+ ["What is the most important nutrient in a dog's diet?", 60, 0.0],
161
+ ["How often should an adult dog be fed?", 60, 0.0],
162
+ ],
163
+ inputs=[question, max_new_tokens, temperature],
164
+ outputs=answer,
165
+ fn=ask_model,
166
+ )
167
+
168
+ if __name__ == "__main__":
169
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # CPU-only build of PyTorch (keeps the Space small and avoids CUDA wheels)
2
+ --extra-index-url https://download.pytorch.org/whl/cpu
3
+
4
+ torch>=2.2,<3
5
+ transformers>=4.45,<5
6
+ peft>=0.13
7
+ accelerate>=0.34
8
+ sentencepiece>=0.2
9
+ huggingface_hub>=0.25
10
+ gradio>=4.44