ndahlbom commited on
Commit
7038394
·
verified ·
1 Parent(s): 7101a3f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -322
app.py CHANGED
@@ -2,16 +2,14 @@ import gradio as gr
2
  import subprocess
3
  from huggingface_hub import hf_hub_download
4
 
5
- # 1. Install llama-cpp-python in runtime (not via requirements.txt)
6
- # Important: remove `llama-cpp-python` from requirements.txt,
7
- # otherwise Spaces may try to build from source and get stuck.
8
  subprocess.run("pip install -q 'llama_cpp_python==0.3.15'", shell=True, check=False)
9
- from llama_cpp import Llama
10
 
 
11
 
12
- # 2. Load your GGUF model from Hugging Face
13
  MODEL_REPO = "Jeppcode/ScalableLab2"
14
- GGUF_FILENAME = "model-q4_k_m.gguf" # or "model-f16.gguf" if you prefer fp16
15
 
16
  print(f"Downloading GGUF model {MODEL_REPO}/{GGUF_FILENAME} ...")
17
  model_path = hf_hub_download(
@@ -22,38 +20,19 @@ model_path = hf_hub_download(
22
  print("Initializing llama.cpp LLM ...")
23
  llm = Llama(
24
  model_path=model_path,
25
- n_ctx=2048, # context length
26
- n_threads=2, # threads (Spaces CPU is limited)
27
- n_batch=64, # batch size for generation
28
  use_mmap=True,
29
  use_mlock=False,
30
  )
31
 
32
-
33
- # 3. Style presets (system prompts)
34
- STYLE_SYSTEM_PROMPTS = {
35
- "Default": "You are a helpful, polite assistant.",
36
- "Short answer": (
37
- "You are a helpful assistant. Answer as concisely as possible, usually in 1-3 sentences."
38
- ),
39
- "Detailed explanation": (
40
- "You are a helpful teaching assistant. Give clear, structured and detailed explanations, "
41
- "often with bullet points or numbered steps when useful."
42
- ),
43
- "Step-by-step reasoning": (
44
- "You are a careful problem solver. Think step by step and explain your reasoning clearly "
45
- "before giving the final answer."
46
- ),
47
- }
48
-
49
 
50
  def _extract_text_from_content(content):
51
  """
52
- In Gradio 6 ChatInterface, history uses the messages format.
53
- content can be:
54
- - a string
55
- - a list of blocks: [{'type': 'text', 'text': '...'} , ...]
56
- We convert it into a simple string.
57
  """
58
  if isinstance(content, list):
59
  texts = []
@@ -66,84 +45,56 @@ def _extract_text_from_content(content):
66
  else:
67
  return str(content)
68
 
69
-
70
- def build_prompt(message, history, style):
71
  """
72
- Build a simple text prompt for llama.cpp based on:
73
- - chosen style (system prompt)
74
- - conversation history
75
- - latest user message
76
-
77
- Format:
78
- System: ...
79
- Conversation:
80
- User: ...
81
- Assistant: ...
82
- ...
83
- User: <current message>
84
- Assistant:
85
  """
86
- system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
87
-
88
  prompt_parts = []
89
- prompt_parts.append(f"System: {system_prompt}\n")
90
  prompt_parts.append("Conversation:\n")
91
-
92
- # history is a list of dicts: {'role': 'user'/'assistant'/'system', 'content': ...}
93
  for msg in history or []:
94
  role = msg.get("role")
95
  content = _extract_text_from_content(msg.get("content", ""))
96
-
97
  if not content:
98
  continue
99
-
100
  if role == "user":
101
  prompt_parts.append(f"User: {content}\n")
102
  elif role == "assistant":
103
  prompt_parts.append(f"Assistant: {content}\n")
104
  elif role == "system":
105
  prompt_parts.append(f"System (previous): {content}\n")
106
-
107
  # Current user message
108
  prompt_parts.append(f"User: {message}\n")
109
  prompt_parts.append("Assistant:")
110
-
111
  full_prompt = "".join(prompt_parts)
112
  return full_prompt
113
 
114
-
115
- def chat_fn(message, history, max_new_tokens, temperature, top_p, repetition_penalty, style):
116
  """
117
- Main function called by Gradio ChatInterface.
118
- - message: latest user input
119
- - history: previous messages (messages format)
120
- - other params: sliders / radio buttons
121
  """
122
- prompt = build_prompt(message, history, style)
123
-
124
- # Handle deterministic mode when temperature == 0
125
- temp = float(temperature)
126
- top_p_val = float(top_p)
127
- repeat_pen = float(repetition_penalty)
128
-
129
- if temp <= 0.0:
130
- temp = 0.0
131
- top_p_val = 1.0 # less important when temp=0
132
 
133
  output = llm(
134
  prompt,
135
  max_tokens=int(max_new_tokens),
136
- temperature=temp,
137
- top_p=top_p_val,
138
- repeat_penalty=repeat_pen,
139
  stop=["User:", "Assistant:", "System:", "Conversation:"],
140
  )
141
-
142
  reply = output["choices"][0]["text"].strip()
143
  return reply
144
 
145
-
146
- # 4. Sliders and controls (extra inputs to ChatInterface)
147
  max_new_tokens_slider = gr.Slider(
148
  minimum=16,
149
  maximum=256,
@@ -152,258 +103,18 @@ max_new_tokens_slider = gr.Slider(
152
  label="Max new tokens (response length)",
153
  )
154
 
155
- temperature_slider = gr.Slider(
156
- minimum=0.0,
157
- maximum=1.5,
158
- value=0.0,
159
- step=0.1,
160
- label="Temperature (0 = deterministic, higher = more random)",
161
- )
162
-
163
- top_p_slider = gr.Slider(
164
- minimum=0.1,
165
- maximum=1.0,
166
- value=0.9,
167
- step=0.05,
168
- label="Top-p (nucleus sampling)",
169
- )
170
-
171
- repetition_penalty_slider = gr.Slider(
172
- minimum=0.8,
173
- maximum=1.3,
174
- value=1.0,
175
- step=0.05,
176
- label="Repetition penalty",
177
- )
178
-
179
- style_radio = gr.Radio(
180
- choices=[
181
- "Default",
182
- "Short answer",
183
- "Detailed explanation",
184
- "Step-by-step reasoning",
185
- ],
186
- value="Detailed explanation",
187
- label="Answer style",
188
- )
189
-
190
- # 5. Christmas theme: inject CSS + hero directly into description
191
- christmas_style_and_hero = """
192
- <style>
193
- body {
194
- background: radial-gradient(circle at top, #1b1c2b 0, #050611 55%, #000000 100%);
195
- color: #fdf6e3;
196
- font-family: "Georgia", "Times New Roman", serif;
197
- }
198
-
199
- /* Use the repo image as a soft background */
200
- .gradio-container {
201
- background:
202
- linear-gradient(rgba(0,0,0,0.55), rgba(0,0,0,0.85)),
203
- url("file=Cute-Christmas-Background-edit-online-1.jpg");
204
- background-size: cover;
205
- background-position: center;
206
- }
207
-
208
- /* Christmas hero card */
209
- .hero {
210
- position: relative;
211
- margin: 0 auto 1.5rem auto;
212
- max-width: 900px;
213
- padding: 1.6rem 1.6rem 1.4rem 1.6rem;
214
- border-radius: 20px;
215
- border: 1px solid rgba(255, 255, 255, 0.14);
216
- background:
217
- radial-gradient(circle at top,
218
- rgba(255, 255, 255, 0.15),
219
- rgba(5, 5, 15, 0.98)
220
- );
221
- box-shadow:
222
- 0 0 28px rgba(0, 0, 0, 0.9),
223
- 0 0 70px rgba(180, 0, 40, 0.55);
224
- overflow: hidden;
225
- }
226
-
227
- .hero-inner {
228
- position: relative;
229
- z-index: 1;
230
- display: flex;
231
- gap: 1.2rem;
232
- align-items: center;
233
- }
234
-
235
- .hero-badge {
236
- flex-shrink: 0;
237
- width: 92px;
238
- height: 92px;
239
- border-radius: 999px;
240
- overflow: hidden;
241
- border: 2px solid rgba(255, 255, 255, 0.8);
242
- box-shadow:
243
- 0 0 24px rgba(0, 0, 0, 0.9),
244
- 0 0 30px rgba(0, 160, 90, 0.7);
245
- background:
246
- radial-gradient(circle at top,
247
- rgba(255,255,255,0.3),
248
- rgba(5,5,10,1)
249
- ),
250
- url("file=Cute-Christmas-Background-edit-online-1.jpg");
251
- background-size: cover;
252
- background-position: center;
253
- }
254
-
255
- .hero-text h1 {
256
- margin: 0 0 0.35rem 0;
257
- font-size: 1.35rem;
258
- letter-spacing: 0.08em;
259
- text-transform: uppercase;
260
- color: #ffefe0;
261
- }
262
-
263
- .hero-text p {
264
- margin: 0;
265
- font-size: 0.95rem;
266
- color: #f8eadd;
267
- line-height: 1.5;
268
- }
269
-
270
- .hero-keyline {
271
- margin-top: 1rem;
272
- height: 1px;
273
- background-image: linear-gradient(
274
- 90deg,
275
- rgba(255, 255, 255, 0),
276
- rgba(255, 225, 150, 0.9),
277
- rgba(255, 255, 255, 0)
278
- );
279
- opacity: 0.9;
280
- }
281
-
282
- /* Chat card */
283
- .gr-chat-interface {
284
- position: relative !important;
285
- border-radius: 18px !important;
286
- border: 1px solid rgba(255, 255, 255, 0.16);
287
- background:
288
- linear-gradient(
289
- 135deg,
290
- rgba(5, 10, 20, 0.96),
291
- rgba(10, 15, 30, 0.96)
292
- );
293
- box-shadow:
294
- 0 0 24px rgba(0, 0, 0, 0.9),
295
- 0 0 50px rgba(0, 180, 120, 0.45);
296
- overflow: hidden;
297
- }
298
-
299
- /* Chat messages as gift tags */
300
- .gr-chat-message {
301
- position: relative;
302
- border-radius: 14px !important;
303
- border: 1px solid rgba(255, 255, 255, 0.06) !important;
304
- backdrop-filter: blur(4px);
305
- }
306
-
307
- .gr-chat-message.user {
308
- background:
309
- radial-gradient(circle at top left,
310
- rgba(0, 180, 120, 0.28),
311
- rgba(10, 15, 25, 0.98)
312
- ) !important;
313
- border-left: 4px solid #00c278 !important;
314
- }
315
-
316
- .gr-chat-message.bot {
317
- background:
318
- radial-gradient(circle at top left,
319
- rgba(230, 30, 90, 0.32),
320
- rgba(10, 10, 24, 0.98)
321
- ) !important;
322
- border-left: 4px solid #ff4060 !important;
323
- }
324
-
325
- /* Input area */
326
- textarea, .gr-text-input, .gr-textbox {
327
- background: rgba(5, 10, 20, 0.98) !important;
328
- border-radius: 999px !important;
329
- border: 1px solid rgba(255, 255, 255, 0.4) !important;
330
- color: #fffbf3 !important;
331
- }
332
-
333
- /* Buttons */
334
- button, .gr-button {
335
- background: linear-gradient(135deg, #ff4060, #00c278) !important;
336
- border-radius: 999px !important;
337
- border: none !important;
338
- color: #fffbf3 !important;
339
- font-weight: 600 !important;
340
- letter-spacing: 0.08em;
341
- text-transform: uppercase;
342
- box-shadow:
343
- 0 0 16px rgba(0, 0, 0, 0.9),
344
- 0 0 26px rgba(255, 204, 140, 0.6);
345
- }
346
-
347
- button:hover, .gr-button:hover {
348
- filter: brightness(1.07);
349
- box-shadow:
350
- 0 0 18px rgba(255, 90, 120, 0.8),
351
- 0 0 32px rgba(0, 200, 150, 0.7);
352
- }
353
-
354
- /* Sliders and controls */
355
- input[type="range"] {
356
- accent-color: #ff4060;
357
- }
358
-
359
- /* Scrollbar */
360
- ::-webkit-scrollbar {
361
- width: 8px;
362
- }
363
- ::-webkit-scrollbar-track {
364
- background: transparent;
365
- }
366
- ::-webkit-scrollbar-thumb {
367
- background: rgba(255, 255, 255, 0.5);
368
- border-radius: 999px;
369
- }
370
- </style>
371
-
372
- <div class="hero">
373
- <div class="hero-inner">
374
- <div class="hero-badge"></div>
375
- <div class="hero-text">
376
- <h1>Scalable Lab 2 Christmas Chat</h1>
377
- <p>
378
- Talk to our fine tuned Llama based model, wrapped as a compact GGUF
379
- and running on CPU. Use the controls in the accordion below to tune
380
- response length, randomness and style like a Christmas DJ for language models.
381
- </p>
382
- </div>
383
- </div>
384
- <div class="hero-keyline"></div>
385
- </div>
386
-
387
- <p>
388
- 🎄 <strong>Tip:</strong> Try switching between short answers and step by step reasoning,
389
- and play with temperature and top p to see how the model behaves.
390
- </p>
391
- """
392
-
393
-
394
  demo = gr.ChatInterface(
395
  fn=chat_fn,
396
  title="Lab 2 – Fine-tuned GGUF model",
397
- description=christmas_style_and_hero,
 
 
 
398
  additional_inputs=[
399
  max_new_tokens_slider,
400
- temperature_slider,
401
- top_p_slider,
402
- repetition_penalty_slider,
403
- style_radio,
404
  ],
405
  additional_inputs_accordion="Generation controls",
406
  )
407
 
408
  if __name__ == "__main__":
409
- demo.launch()
 
2
  import subprocess
3
  from huggingface_hub import hf_hub_download
4
 
5
+ # 1. Install llama-cpp-python in runtime
 
 
6
  subprocess.run("pip install -q 'llama_cpp_python==0.3.15'", shell=True, check=False)
 
7
 
8
+ from llama_cpp import Llama
9
 
10
+ # 2. Load GGUF model from Hugging Face
11
  MODEL_REPO = "Jeppcode/ScalableLab2"
12
+ GGUF_FILENAME = "model-q4_k_m.gguf"
13
 
14
  print(f"Downloading GGUF model {MODEL_REPO}/{GGUF_FILENAME} ...")
15
  model_path = hf_hub_download(
 
20
  print("Initializing llama.cpp LLM ...")
21
  llm = Llama(
22
  model_path=model_path,
23
+ n_ctx=2048,
24
+ n_threads=2,
25
+ n_batch=64,
26
  use_mmap=True,
27
  use_mlock=False,
28
  )
29
 
30
+ # Hardcoded system prompt (since style selector is removed)
31
+ SYSTEM_PROMPT = "You are a helpful teaching assistant. Give clear, structured and detailed explanations."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  def _extract_text_from_content(content):
34
  """
35
+ Extracts text from Gradio 6 message format.
 
 
 
 
36
  """
37
  if isinstance(content, list):
38
  texts = []
 
45
  else:
46
  return str(content)
47
 
48
+ def build_prompt(message, history):
 
49
  """
50
+ Builds the prompt using the hardcoded system prompt.
 
 
 
 
 
 
 
 
 
 
 
 
51
  """
 
 
52
  prompt_parts = []
53
+ prompt_parts.append(f"System: {SYSTEM_PROMPT}\n")
54
  prompt_parts.append("Conversation:\n")
55
+
 
56
  for msg in history or []:
57
  role = msg.get("role")
58
  content = _extract_text_from_content(msg.get("content", ""))
 
59
  if not content:
60
  continue
 
61
  if role == "user":
62
  prompt_parts.append(f"User: {content}\n")
63
  elif role == "assistant":
64
  prompt_parts.append(f"Assistant: {content}\n")
65
  elif role == "system":
66
  prompt_parts.append(f"System (previous): {content}\n")
67
+
68
  # Current user message
69
  prompt_parts.append(f"User: {message}\n")
70
  prompt_parts.append("Assistant:")
 
71
  full_prompt = "".join(prompt_parts)
72
  return full_prompt
73
 
74
+ def chat_fn(message, history, max_new_tokens):
 
75
  """
76
+ Main chat function.
77
+ Only accepts max_new_tokens as an additional input now.
 
 
78
  """
79
+ prompt = build_prompt(message, history)
80
+
81
+ # Internal defaults for the removed sliders
82
+ temperature = 0.7
83
+ top_p = 0.9
84
+ repetition_penalty = 1.0
 
 
 
 
85
 
86
  output = llm(
87
  prompt,
88
  max_tokens=int(max_new_tokens),
89
+ temperature=temperature,
90
+ top_p=top_p,
91
+ repeat_penalty=repetition_penalty,
92
  stop=["User:", "Assistant:", "System:", "Conversation:"],
93
  )
 
94
  reply = output["choices"][0]["text"].strip()
95
  return reply
96
 
97
+ # 4. Only keep the Max Token slider
 
98
  max_new_tokens_slider = gr.Slider(
99
  minimum=16,
100
  maximum=256,
 
103
  label="Max new tokens (response length)",
104
  )
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  demo = gr.ChatInterface(
107
  fn=chat_fn,
108
  title="Lab 2 – Fine-tuned GGUF model",
109
+ description=(
110
+ "Chat with our fine-tuned Llama-based model, converted to GGUF and "
111
+ "loaded via llama.cpp from Jeppcode/ScalableLab2."
112
+ ),
113
  additional_inputs=[
114
  max_new_tokens_slider,
 
 
 
 
115
  ],
116
  additional_inputs_accordion="Generation controls",
117
  )
118
 
119
  if __name__ == "__main__":
120
+ demo.launch()