Jeppcode commited on
Commit
2da4631
·
verified ·
1 Parent(s): 6e74217

Rename Jeppapp.py to app.py

Browse files
Files changed (1) hide show
  1. Jeppapp.py → app.py +114 -100
Jeppapp.py → app.py RENAMED
@@ -1,29 +1,36 @@
1
  import gradio as gr
2
- import torch
3
- from transformers import AutoModelForCausalLM, AutoTokenizer
4
 
5
- MODEL_ID = "Jeppcode/ScalableLab2"
6
- SUBFOLDER = "merged-model-fp16"
 
 
 
7
 
8
- print(f"Loading model {MODEL_ID}/{SUBFOLDER} ...")
9
 
10
- # Tokenizer
11
- tokenizer = AutoTokenizer.from_pretrained(
12
- MODEL_ID,
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 på CPU
 
23
  )
24
- model.eval()
25
 
26
- # Några stil-lägen som systemprompter
 
27
  STYLE_SYSTEM_PROMPTS = {
28
  "Default": "You are a helpful, polite assistant.",
29
  "Short answer": (
@@ -40,99 +47,102 @@ STYLE_SYSTEM_PROMPTS = {
40
  }
41
 
42
 
43
- def build_prompt(message, history, style):
44
  """
45
- I Gradio 6 är history en lista av dicts:
46
- [
47
- {"role": "user", "content": [...]},
48
- {"role": "assistant", "content": [...]},
49
- ...
50
- ]
51
- Vi plockar ut texten och mappar till {role, content}, och lägger till en systemprompt
52
- baserat på vald 'style'.
53
  """
54
- messages = []
 
 
 
 
 
 
 
 
 
 
55
 
56
- # Lägg till system / style prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
58
- messages.append({"role": "system", "content": system_prompt})
59
 
60
- # Tidigare historik
61
- for msg in history:
 
 
 
 
62
  role = msg.get("role")
63
- content = msg.get("content", "")
64
-
65
- # content kan vara en lista av blocks eller en sträng
66
- if isinstance(content, list):
67
- texts = []
68
- for block in content:
69
- if isinstance(block, dict) and block.get("type") == "text":
70
- texts.append(block.get("text", ""))
71
- else:
72
- texts.append(str(block))
73
- text = "\n".join(t for t in texts if t)
74
- else:
75
- text = str(content)
76
-
77
- if text and role in ("user", "assistant", "system"):
78
- messages.append({"role": role, "content": text})
79
-
80
- # nuvarande användarmeddelande
81
- messages.append({"role": "user", "content": message})
82
-
83
- prompt = tokenizer.apply_chat_template(
84
- messages,
85
- tokenize=False,
86
- add_generation_prompt=True,
87
- )
88
- return prompt
89
 
 
 
90
 
91
- def chat_fn(message, history, max_new_tokens, temperature, top_p, repetition_penalty, style):
92
- # Bygg prompt med historik + stil
93
- prompt = build_prompt(message, history, style)
 
 
 
 
 
 
 
 
 
 
94
 
95
- inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
96
-
97
- gen_kwargs = {
98
- **inputs,
99
- "max_new_tokens": int(max_new_tokens),
100
- "pad_token_id": tokenizer.eos_token_id,
101
- "eos_token_id": tokenizer.eos_token_id,
102
- "repetition_penalty": float(repetition_penalty),
103
- }
104
-
105
- # Deterministisk om temperature == 0, annars sampling
106
- if temperature <= 0.0:
107
- gen_kwargs.update(
108
- dict(
109
- do_sample=False,
110
- temperature=None,
111
- top_p=None,
112
- )
113
- )
114
- else:
115
- gen_kwargs.update(
116
- dict(
117
- do_sample=True,
118
- temperature=float(temperature),
119
- top_p=float(top_p),
120
- )
121
- )
122
 
123
- with torch.no_grad():
124
- outputs = model.generate(**gen_kwargs)
 
 
 
 
 
 
125
 
126
- generated = tokenizer.decode(
127
- outputs[0][inputs["input_ids"].shape[1]:],
128
- skip_special_tokens=True,
129
- ).strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
- # ChatInterface sköter history själv, vi returnerar bara svaret
132
- return generated
133
 
134
 
135
- # DJ-reglagen (extra inputs till ChatInterface)
136
  max_new_tokens_slider = gr.Slider(
137
  minimum=16,
138
  maximum=256,
@@ -140,6 +150,7 @@ max_new_tokens_slider = gr.Slider(
140
  step=8,
141
  label="Max new tokens (response length)",
142
  )
 
143
  temperature_slider = gr.Slider(
144
  minimum=0.0,
145
  maximum=1.5,
@@ -147,6 +158,7 @@ temperature_slider = gr.Slider(
147
  step=0.1,
148
  label="Temperature (0 = deterministic, higher = more random)",
149
  )
 
150
  top_p_slider = gr.Slider(
151
  minimum=0.1,
152
  maximum=1.0,
@@ -154,6 +166,7 @@ top_p_slider = gr.Slider(
154
  step=0.05,
155
  label="Top-p (nucleus sampling)",
156
  )
 
157
  repetition_penalty_slider = gr.Slider(
158
  minimum=0.8,
159
  maximum=1.3,
@@ -161,6 +174,7 @@ repetition_penalty_slider = gr.Slider(
161
  step=0.05,
162
  label="Repetition penalty",
163
  )
 
164
  style_radio = gr.Radio(
165
  choices=[
166
  "Default",
@@ -174,10 +188,10 @@ style_radio = gr.Radio(
174
 
175
  demo = gr.ChatInterface(
176
  fn=chat_fn,
177
- title="Lab 2 – Fine-tuned merged model (fp16)",
178
  description=(
179
- "Chat with our fine-tuned Llama-based model, merged to fp16 and "
180
- "loaded from Jeppcode/ScalableLab2/merged-model-fp16.\n\n"
181
  "Use the controls in the accordion below like a DJ board to tweak "
182
  "response length, randomness and style."
183
  ),
 
1
  import gradio as gr
2
+ import subprocess
3
+ from huggingface_hub import hf_hub_download
4
 
5
+ # 1. Install llama-cpp-python i runtime (inte via requirements.txt)
6
+ # Viktigt: ta bort `llama-cpp-python` från requirements.txt,
7
+ # annars försöker Spaces bygga från källkod och fastnar.
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. Ladda din GGUF-modell från Hugging Face
13
+ MODEL_REPO = "Jeppcode/ScalableLab2"
14
+ GGUF_FILENAME = "model-q4_k_m.gguf" # eller "model-f16.gguf" om du vill ha fp16-varianten
15
+
16
+ print(f"Downloading GGUF model {MODEL_REPO}/{GGUF_FILENAME} ...")
17
+ model_path = hf_hub_download(
18
+ repo_id=MODEL_REPO,
19
+ filename=GGUF_FILENAME,
20
  )
21
 
22
+ print("Initializing llama.cpp LLM ...")
23
+ llm = Llama(
24
+ model_path=model_path,
25
+ n_ctx=2048, # kontextlängd
26
+ n_threads=2, # trådar (Spaces CPU är begränsad)
27
+ n_batch=64, # batchstorlek för generation
28
+ use_mmap=True,
29
+ use_mlock=False,
30
  )
 
31
 
32
+
33
+ # 3. Några stil-lägen som "system prompts"
34
  STYLE_SYSTEM_PROMPTS = {
35
  "Default": "You are a helpful, polite assistant.",
36
  "Short answer": (
 
47
  }
48
 
49
 
50
+ def _extract_text_from_content(content):
51
  """
52
+ Gradio 6 ChatInterface använder 'messages'-format.
53
+ content kan vara:
54
+ - en sträng
55
+ - en lista av blocks: [{"type": "text", "text": "..."} , ...]
56
+ Vi konverterar det till en enkel sträng.
 
 
 
57
  """
58
+ if isinstance(content, list):
59
+ texts = []
60
+ for block in content:
61
+ if isinstance(block, dict) and block.get("type") == "text":
62
+ texts.append(block.get("text", ""))
63
+ else:
64
+ texts.append(str(block))
65
+ return "\n".join(t for t in texts if t)
66
+ else:
67
+ return str(content)
68
+
69
 
70
+ def build_prompt(message, history, style):
71
+ """
72
+ Bygger en enkel textprompt för llama.cpp baserat på:
73
+ - vald stil (system prompt)
74
+ - konversationshistorik
75
+ - senaste user-meddelandet
76
+ Vi använder ett simpelt format:
77
+ System: ...
78
+ Conversation:
79
+ User: ...
80
+ Assistant: ...
81
+ ...
82
+ User: <current message>
83
+ Assistant:
84
+ """
85
  system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
 
86
 
87
+ prompt_parts = []
88
+ prompt_parts.append(f"System: {system_prompt}\n")
89
+ prompt_parts.append("Conversation:\n")
90
+
91
+ # history är en lista av dicts: {"role": "...", "content": ...}
92
+ for msg in history or []:
93
  role = msg.get("role")
94
+ content = _extract_text_from_content(msg.get("content", ""))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
+ if not content:
97
+ continue
98
 
99
+ if role == "user":
100
+ prompt_parts.append(f"User: {content}\n")
101
+ elif role == "assistant":
102
+ prompt_parts.append(f"Assistant: {content}\n")
103
+ elif role == "system":
104
+ prompt_parts.append(f"System (previous): {content}\n")
105
+
106
+ # Nuvarande användarmeddelande
107
+ prompt_parts.append(f"User: {message}\n")
108
+ prompt_parts.append("Assistant:")
109
+
110
+ full_prompt = "".join(prompt_parts)
111
+ return full_prompt
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
+ def chat_fn(message, history, max_new_tokens, temperature, top_p, repetition_penalty, style):
115
+ """
116
+ Huvudfunktionen som Gradio ChatInterface anropar.
117
+ - message: senaste user input
118
+ - history: tidigare meddelanden (messages-format)
119
+ - övriga parametrar: sliders / radio-knappar
120
+ """
121
+ prompt = build_prompt(message, history, style)
122
 
123
+ # Hantera deterministiskt läge om temperature == 0
124
+ temp = float(temperature)
125
+ top_p_val = float(top_p)
126
+ repeat_pen = float(repetition_penalty)
127
+
128
+ if temp <= 0.0:
129
+ temp = 0.0
130
+ top_p_val = 1.0 # spelar mindre roll när temp=0
131
+
132
+ output = llm(
133
+ prompt,
134
+ max_tokens=int(max_new_tokens),
135
+ temperature=temp,
136
+ top_p=top_p_val,
137
+ repeat_penalty=repeat_pen,
138
+ stop=["User:", "Assistant:", "System:", "Conversation:"],
139
+ )
140
 
141
+ reply = output["choices"][0]["text"].strip()
142
+ return reply
143
 
144
 
145
+ # 4. DJ-reglagen (extra inputs till ChatInterface)
146
  max_new_tokens_slider = gr.Slider(
147
  minimum=16,
148
  maximum=256,
 
150
  step=8,
151
  label="Max new tokens (response length)",
152
  )
153
+
154
  temperature_slider = gr.Slider(
155
  minimum=0.0,
156
  maximum=1.5,
 
158
  step=0.1,
159
  label="Temperature (0 = deterministic, higher = more random)",
160
  )
161
+
162
  top_p_slider = gr.Slider(
163
  minimum=0.1,
164
  maximum=1.0,
 
166
  step=0.05,
167
  label="Top-p (nucleus sampling)",
168
  )
169
+
170
  repetition_penalty_slider = gr.Slider(
171
  minimum=0.8,
172
  maximum=1.3,
 
174
  step=0.05,
175
  label="Repetition penalty",
176
  )
177
+
178
  style_radio = gr.Radio(
179
  choices=[
180
  "Default",
 
188
 
189
  demo = gr.ChatInterface(
190
  fn=chat_fn,
191
+ title="Lab 2 – Fine-tuned GGUF model",
192
  description=(
193
+ "Chat with our fine-tuned Llama-based model, converted to GGUF and "
194
+ "loaded via llama.cpp from Jeppcode/ScalableLab2.\n\n"
195
  "Use the controls in the accordion below like a DJ board to tweak "
196
  "response length, randomness and style."
197
  ),