Jeppcode commited on
Commit
1d479c9
·
verified ·
1 Parent(s): e776b8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -50
app.py CHANGED
@@ -13,49 +13,53 @@ tokenizer = AutoTokenizer.from_pretrained(
13
  subfolder=SUBFOLDER,
14
  )
15
 
16
- # Modell – fp16 och snålare på CPU
17
  model = AutoModelForCausalLM.from_pretrained(
18
  MODEL_ID,
19
  subfolder=SUBFOLDER,
20
- dtype=torch.float16, # samma som torch_dtype men utan varningen
21
  low_cpu_mem_usage=True,
22
- device_map="cpu", # var explicit, allt CPU
23
  )
24
  model.eval()
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- def build_prompt(message, history):
28
  """
29
- I Gradio 6 är history en lista av dicts:
30
- [
31
- {"role": "user", "content": [...]},
32
- {"role": "assistant", "content": [...]},
33
- ...
34
- ]
35
- Vi plockar ut texten och mappar till {role, content}.
36
  """
37
  messages = []
38
 
39
- for msg in history:
40
- role = msg.get("role")
41
- content = msg.get("content", "")
42
-
43
- # content kan vara en lista av blocks eller en sträng
44
- if isinstance(content, list):
45
- texts = []
46
- for block in content:
47
- if isinstance(block, dict) and block.get("type") == "text":
48
- texts.append(block.get("text", ""))
49
- else:
50
- texts.append(str(block))
51
- text = "\n".join(t for t in texts if t)
52
- else:
53
- text = str(content)
54
-
55
- if text:
56
- messages.append({"role": role, "content": text})
57
-
58
- # nuvarande användarmeddelande
59
  messages.append({"role": "user", "content": message})
60
 
61
  prompt = tokenizer.apply_chat_template(
@@ -66,38 +70,128 @@ def build_prompt(message, history):
66
  return prompt
67
 
68
 
69
- def chat_fn(message, history):
70
- prompt = build_prompt(message, history)
 
71
 
72
  inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
73
 
74
- with torch.no_grad():
75
- outputs = model.generate(
76
- **inputs,
77
- max_new_tokens=64, # kortare svar för snabbare CPU
78
- do_sample=False, # deterministiskt
79
- temperature=None,
80
- top_p=None,
81
- pad_token_id=tokenizer.eos_token_id,
82
- eos_token_id=tokenizer.eos_token_id,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  )
84
 
 
 
 
85
  generated = tokenizer.decode(
86
  outputs[0][inputs["input_ids"].shape[1]:],
87
  skip_special_tokens=True,
88
  ).strip()
89
 
90
- return generated
 
 
91
 
92
 
93
- demo = gr.ChatInterface(
94
- fn=chat_fn,
95
- title="Lab 2 – Fine-tuned merged model (fp16)",
96
- description=(
97
  "Chat with our fine-tuned Llama-based model, merged to fp16 and "
98
- "loaded from Jeppcode/ScalableLab2/merged-model-fp16."
99
- ),
100
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  if __name__ == "__main__":
103
  demo.launch()
 
13
  subfolder=SUBFOLDER,
14
  )
15
 
16
+ # Model – fp16 on CPU, memory-friendly
17
  model = AutoModelForCausalLM.from_pretrained(
18
  MODEL_ID,
19
  subfolder=SUBFOLDER,
20
+ dtype=torch.float16,
21
  low_cpu_mem_usage=True,
22
+ device_map="cpu", # explicit: everything on CPU
23
  )
24
  model.eval()
25
 
26
+ STYLE_SYSTEM_PROMPTS = {
27
+ "Default": "You are a helpful, polite assistant.",
28
+ "Short answer": (
29
+ "You are a helpful assistant. Answer as concisely as possible, usually in 1–3 sentences."
30
+ ),
31
+ "Detailed explanation": (
32
+ "You are a helpful teaching assistant. Give clear, structured and detailed explanations, "
33
+ "often with bullet points or numbered steps when useful."
34
+ ),
35
+ "Step-by-step reasoning": (
36
+ "You are a careful problem solver. Think step by step and explain your reasoning clearly "
37
+ "before giving the final answer."
38
+ ),
39
+ }
40
+
41
 
42
+ def build_prompt(message, history, style):
43
  """
44
+ history från gr.Chatbot är en lista av [user, bot]-par:
45
+ [["Hi", "Hello!"], ["Explain X", "Answer..."], ...]
46
+ Vi konverterar till ett messages-format och lägger på en systemprompt
47
+ baserat vald style.
 
 
 
48
  """
49
  messages = []
50
 
51
+ # System / style prompt
52
+ system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
53
+ messages.append({"role": "system", "content": system_prompt})
54
+
55
+ # Tidigare dialog
56
+ for user_msg, bot_msg in history:
57
+ if user_msg:
58
+ messages.append({"role": "user", "content": user_msg})
59
+ if bot_msg:
60
+ messages.append({"role": "assistant", "content": bot_msg})
61
+
62
+ # Nuvarande användarmeddelande
 
 
 
 
 
 
 
 
63
  messages.append({"role": "user", "content": message})
64
 
65
  prompt = tokenizer.apply_chat_template(
 
70
  return prompt
71
 
72
 
73
+ def chat_fn(message, history, max_new_tokens, temperature, top_p, repetition_penalty, style):
74
+ # Bygg prompt med historik + style
75
+ prompt = build_prompt(message, history, style)
76
 
77
  inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
78
 
79
+ gen_kwargs = {
80
+ **inputs,
81
+ "max_new_tokens": int(max_new_tokens),
82
+ "pad_token_id": tokenizer.eos_token_id,
83
+ "eos_token_id": tokenizer.eos_token_id,
84
+ "repetition_penalty": float(repetition_penalty),
85
+ }
86
+
87
+ # Greedy vs sampling beroende på temperatur
88
+ if temperature <= 0.0:
89
+ gen_kwargs.update(
90
+ dict(
91
+ do_sample=False,
92
+ temperature=None,
93
+ top_p=None,
94
+ )
95
+ )
96
+ else:
97
+ gen_kwargs.update(
98
+ dict(
99
+ do_sample=True,
100
+ temperature=float(temperature),
101
+ top_p=float(top_p),
102
+ )
103
  )
104
 
105
+ with torch.no_grad():
106
+ outputs = model.generate(**gen_kwargs)
107
+
108
  generated = tokenizer.decode(
109
  outputs[0][inputs["input_ids"].shape[1]:],
110
  skip_special_tokens=True,
111
  ).strip()
112
 
113
+ # Lägg till ny rad i historiken och töm textboxen
114
+ history = history + [[message, generated]]
115
+ return "", history
116
 
117
 
118
+ with gr.Blocks() as demo:
119
+ gr.Markdown(
120
+ "# Lab 2 – Fine-tuned merged model (fp16)\n"
 
121
  "Chat with our fine-tuned Llama-based model, merged to fp16 and "
122
+ "loaded from `Jeppcode/ScalableLab2/merged-model-fp16`.\n\n"
123
+ "Use the controls on the right like a DJ board to explore how decoding "
124
+ "settings change the behaviour of the model."
125
+ )
126
+
127
+ with gr.Row():
128
+ # Left: chat
129
+ with gr.Column(scale=3):
130
+ chatbot = gr.Chatbot(label="Chat")
131
+ msg = gr.Textbox(
132
+ label="Your message",
133
+ placeholder="Ask the model something...",
134
+ lines=3,
135
+ )
136
+ send_btn = gr.Button("Send")
137
+ clear_btn = gr.Button("Clear chat")
138
+
139
+ # Right: generation controls
140
+ with gr.Column(scale=1):
141
+ gr.Markdown("### Generation controls")
142
+
143
+ max_new_tokens = gr.Slider(
144
+ minimum=16,
145
+ maximum=256,
146
+ value=64,
147
+ step=8,
148
+ label="Max new tokens (response length)",
149
+ )
150
+ temperature = gr.Slider(
151
+ minimum=0.0,
152
+ maximum=1.5,
153
+ value=0.0,
154
+ step=0.1,
155
+ label="Temperature (0 = deterministic, higher = more random)",
156
+ )
157
+ top_p = gr.Slider(
158
+ minimum=0.1,
159
+ maximum=1.0,
160
+ value=0.9,
161
+ step=0.05,
162
+ label="Top-p (nucleus sampling)",
163
+ )
164
+ repetition_penalty = gr.Slider(
165
+ minimum=0.8,
166
+ maximum=1.3,
167
+ value=1.0,
168
+ step=0.05,
169
+ label="Repetition penalty",
170
+ )
171
+
172
+ style = gr.Radio(
173
+ choices=[
174
+ "Default",
175
+ "Short answer",
176
+ "Detailed explanation",
177
+ "Step-by-step reasoning",
178
+ ],
179
+ value="Detailed explanation",
180
+ label="Answer style",
181
+ )
182
+
183
+ # Koppla knapparna
184
+ send_btn.click(
185
+ chat_fn,
186
+ inputs=[msg, chatbot, max_new_tokens, temperature, top_p, repetition_penalty, style],
187
+ outputs=[msg, chatbot],
188
+ )
189
+ msg.submit(
190
+ chat_fn,
191
+ inputs=[msg, chatbot, max_new_tokens, temperature, top_p, repetition_penalty, style],
192
+ outputs=[msg, chatbot],
193
+ )
194
+ clear_btn.click(lambda: [], None, chatbot)
195
 
196
  if __name__ == "__main__":
197
  demo.launch()