ndahlbom commited on
Commit
bdc4337
·
verified ·
1 Parent(s): 91f318f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -133
app.py CHANGED
@@ -1,7 +1,5 @@
1
  import gradio as gr
2
  import subprocess
3
- import base64
4
- import os
5
  from huggingface_hub import hf_hub_download
6
 
7
  # --- 1. Setup & Install ---
@@ -18,11 +16,10 @@ try:
18
  repo_id=MODEL_REPO,
19
  filename=GGUF_FILENAME,
20
  )
21
- except Exception as e:
22
- print(f"Error downloading model: {e}")
23
- # Fallback for debugging if download fails
24
- model_path = ""
25
 
 
26
  if model_path:
27
  print("Initializing llama.cpp LLM ...")
28
  llm = Llama(
@@ -33,169 +30,189 @@ if model_path:
33
  use_mmap=True,
34
  use_mlock=False,
35
  )
36
- else:
37
- print("WARNING: Model path invalid. App will start but chat will fail.")
38
-
39
- # --- 3. Image Handling (The Fix) ---
40
- def get_background_image_css():
41
- """
42
- Tries to load local image. If missing, uses a URL fallback.
43
- Returns the CSS string for the background.
44
- """
45
- local_img = "Cute-Christmas-Background-edit-online-1.jpg"
46
-
47
- # 1. Try Local Base64
48
- if os.path.exists(local_img):
49
- print(f"Found local image: {local_img}. Encoding...")
50
- with open(local_img, "rb") as f:
51
- encoded = base64.b64encode(f.read()).decode('utf-8')
52
- img_url = f"data:image/jpeg;base64,{encoded}"
53
- # 2. Fallback to URL if local fails
54
- else:
55
- print(f"⚠️ Could not find {local_img}. Using fallback URL.")
56
- img_url = "https://images.unsplash.com/photo-1544976735-a10c71a39644?q=80&w=2560&auto=format&fit=crop"
57
-
58
- return f"""
59
- body, .gradio-container, .gradio-app {{
60
- background-image: url('{img_url}') !important;
61
- background-size: cover !important;
62
- background-position: center center !important;
63
- background-attachment: fixed !important;
64
- background-repeat: no-repeat !important;
65
- background-color: #0b121e !important; /* Fallback color */
66
- }}
67
- """
68
-
69
- bg_css_rule = get_background_image_css()
70
-
71
- # --- 4. Prompts & Logic ---
72
  STYLE_SYSTEM_PROMPTS = {
73
  "Default": "You are a helpful, polite assistant.",
74
- "Short answer": "You are a helpful assistant. Answer as concisely as possible, usually in 1–3 sentences.",
75
- "Detailed explanation": "You are a helpful teaching assistant. Give clear, structured and detailed explanations.",
76
- "Step-by-step reasoning": "You are a careful problem solver. Think step by step and explain your reasoning clearly.",
77
  }
78
 
79
  def _extract_text(content):
80
  if isinstance(content, list):
81
- return "\n".join(
82
- block.get("text", "") for block in content
83
- if isinstance(block, dict) and block.get("type") == "text"
84
- )
85
  return str(content)
86
 
87
- def build_prompt(message, history, style):
88
- system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
89
- prompt_parts = [f"System: {system_prompt}\n", "Conversation:\n"]
90
 
 
 
 
91
  for msg in history or []:
92
  role = msg.get("role")
93
- content = _extract_text(msg.get("content", ""))
94
- if content:
95
- if role == "user": prompt_parts.append(f"User: {content}\n")
96
- elif role == "assistant": prompt_parts.append(f"Assistant: {content}\n")
97
-
98
- prompt_parts.append(f"User: {message}\n")
99
- prompt_parts.append("Assistant:")
100
- return "".join(prompt_parts)
101
-
102
- def chat_fn(message, history, max_new_tokens, style):
103
- # Safe defaults
104
- temperature = 0.7
105
- top_p = 0.9
106
- repetition_penalty = 1.1
107
- prompt = build_prompt(message, history, style)
108
-
109
- # Check if LLM loaded correctly
110
- if 'llm' not in globals():
111
- return "Error: Model not loaded."
112
 
113
  output = llm(
114
  prompt,
115
  max_tokens=int(max_new_tokens),
116
- temperature=temperature,
117
- top_p=top_p,
118
- repeat_penalty=repetition_penalty,
119
- stop=["User:", "Assistant:", "System:", "Conversation:"],
120
  )
121
  return output["choices"][0]["text"].strip()
122
 
123
- # --- 5. Theme & CSS ---
124
-
125
- # A robust theme base
126
- winter_theme = gr.themes.Soft(
127
- primary_hue="blue",
128
- neutral_hue="slate",
129
- ).set(
130
- body_background_fill="transparent",
131
- block_background_fill="rgba(15, 23, 42, 0.7)",
132
- border_color_primary="#FFFFFF",
133
- button_primary_background_fill="#FFFFFF",
134
- button_primary_text_color="#000000",
135
- )
136
-
137
- # Combined CSS
138
- custom_css = bg_css_rule + """
139
- /* Make the App Wrapper Transparent */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  .gradio-container {
141
  background: transparent !important;
142
  }
143
 
144
- /* Chat & Settings Blocks - Frosty Glass with White Borders */
145
- .group, .form, .bubble-wrap, .chatbot {
146
- background-color: rgba(15, 23, 42, 0.8) !important;
147
- border: 2px solid #FFFFFF !important;
148
- border-radius: 12px !important;
149
- backdrop-filter: blur(5px);
150
- box-shadow: 0 4px 15px rgba(0,0,0,0.5);
151
  }
152
 
153
- /* Specific Chat Bubble Coloring */
154
  .user-message {
155
- background-color: rgba(255, 255, 255, 0.2) !important;
156
- border: 1px solid #FFFFFF !important;
157
- color: #FFFFFF !important;
158
  }
 
159
  .bot-message {
160
- background-color: rgba(0, 0, 0, 0.6) !important;
161
- border: 1px solid #A0A0A0 !important;
162
  color: #E0E0E0 !important;
163
  }
164
 
165
- /* Text Colors */
166
  textarea, input {
167
- background-color: rgba(0, 0, 0, 0.5) !important;
168
- border: 1px solid #FFFFFF !important;
169
  color: white !important;
170
- }
171
- label, span, p, .prose {
172
- color: #FFFFFF !important;
173
- text-shadow: 1px 1px 2px black;
174
  }
175
 
176
- /* Hide Footer */
177
- footer {visibility: hidden}
 
 
 
 
 
178
  """
179
 
180
- max_new_tokens_slider = gr.Slider(
181
- minimum=16, maximum=256, value=64, step=8, label="Max Response Length",
182
- )
183
- style_radio = gr.Radio(
184
- choices=["Default", "Short answer", "Detailed explanation"],
185
- value="Detailed explanation",
186
- label="Answer style",
187
- )
188
-
189
- # Instantiate
190
- demo = gr.ChatInterface(
191
- fn=chat_fn,
192
- title="❄️ WinterChat Lab 2 ❄️",
193
- description="Stay frosty. Chat with the fine-tuned model.",
194
- additional_inputs=[max_new_tokens_slider, style_radio],
195
- additional_inputs_accordion="Settings",
196
- theme=winter_theme,
197
- css=custom_css
198
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  if __name__ == "__main__":
201
  demo.launch(allowed_paths=["."])
 
1
  import gradio as gr
2
  import subprocess
 
 
3
  from huggingface_hub import hf_hub_download
4
 
5
  # --- 1. Setup & Install ---
 
16
  repo_id=MODEL_REPO,
17
  filename=GGUF_FILENAME,
18
  )
19
+ except Exception:
20
+ model_path = "" # Handle offline/error gracefully
 
 
21
 
22
+ llm = None
23
  if model_path:
24
  print("Initializing llama.cpp LLM ...")
25
  llm = Llama(
 
30
  use_mmap=True,
31
  use_mlock=False,
32
  )
33
+
34
+ # --- 3. Chat Logic ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  STYLE_SYSTEM_PROMPTS = {
36
  "Default": "You are a helpful, polite assistant.",
37
+ "Short answer": "Answer as concisely as possible, usually in 1–3 sentences.",
38
+ "Detailed explanation": "Give clear, structured and detailed explanations.",
 
39
  }
40
 
41
  def _extract_text(content):
42
  if isinstance(content, list):
43
+ return "\n".join(b.get("text", "") for b in content if isinstance(b, dict) and b.get("type") == "text")
 
 
 
44
  return str(content)
45
 
46
+ def chat_fn(message, history, max_new_tokens, style):
47
+ if not llm: return "Error: Model not loaded."
 
48
 
49
+ # Logic
50
+ system_prompt = STYLE_SYSTEM_PROMPTS.get(style, STYLE_SYSTEM_PROMPTS["Default"])
51
+ prompt = f"System: {system_prompt}\nConversation:\n"
52
  for msg in history or []:
53
  role = msg.get("role")
54
+ txt = _extract_text(msg.get("content", ""))
55
+ if txt:
56
+ if role == "user": prompt += f"User: {txt}\n"
57
+ elif role == "assistant": prompt += f"Assistant: {txt}\n"
58
+ prompt += f"User: {message}\nAssistant:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  output = llm(
61
  prompt,
62
  max_tokens=int(max_new_tokens),
63
+ temperature=0.7,
64
+ top_p=0.9,
65
+ stop=["User:", "Assistant:", "System:"],
 
66
  )
67
  return output["choices"][0]["text"].strip()
68
 
69
+ # --- 4. THEME CSS (The Magic Part) ---
70
+ christmas_css = """
71
+ /* Import a festive/elegant font */
72
+ @import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&family=Lato:wght@400;700&display=swap');
73
+
74
+ body {
75
+ /* Main Background: Snowy Forest */
76
+ background: url('https://images.unsplash.com/photo-1543169176-78e7c10b27b6?q=80&w=2560&auto=format&fit=crop') no-repeat center center fixed;
77
+ background-size: cover;
78
+ color: #f0f0f0;
79
+ font-family: "Lato", sans-serif;
80
+ }
81
+
82
+ /* Headings */
83
+ h1, h2, h3 {
84
+ font-family: "Cinzel", serif;
85
+ color: #FFD700 !important; /* Gold text */
86
+ text-shadow: 0px 2px 4px rgba(0,0,0,0.8);
87
+ text-transform: uppercase;
88
+ }
89
+
90
+ /* 1. HERO SECTION (The Header) */
91
+ .hero {
92
+ position: relative;
93
+ margin: 1rem auto;
94
+ max-width: 900px;
95
+ padding: 2rem;
96
+ border-radius: 20px;
97
+ /* Glassy Red/Dark background */
98
+ background: linear-gradient(135deg, rgba(40, 0, 0, 0.85), rgba(10, 20, 30, 0.9));
99
+ border: 2px solid #D4AF37; /* Gold Border */
100
+ box-shadow: 0 0 30px rgba(0, 0, 0, 0.8), 0 0 10px rgba(212, 175, 55, 0.3);
101
+ overflow: hidden;
102
+ }
103
+
104
+ .hero-inner {
105
+ display: flex;
106
+ gap: 1.5rem;
107
+ align-items: center;
108
+ position: relative;
109
+ z-index: 2;
110
+ }
111
+
112
+ /* The Round Avatar Image */
113
+ .hero-image {
114
+ flex-shrink: 0;
115
+ width: 100px;
116
+ height: 100px;
117
+ border-radius: 50%;
118
+ border: 3px solid #D4AF37; /* Gold */
119
+ overflow: hidden;
120
+ box-shadow: 0 0 20px rgba(0,0,0,0.8);
121
+ }
122
+ .hero-image img {
123
+ width: 100%;
124
+ height: 100%;
125
+ object-fit: cover;
126
+ }
127
+
128
+ .hero-text h1 {
129
+ margin: 0;
130
+ font-size: 1.8rem;
131
+ letter-spacing: 0.1em;
132
+ }
133
+ .hero-text p {
134
+ margin-top: 0.5rem;
135
+ font-size: 1rem;
136
+ color: #E0E0E0;
137
+ line-height: 1.4;
138
+ }
139
+
140
+ /* 2. GRADIO CONTAINER TRANSPARENCY */
141
  .gradio-container {
142
  background: transparent !important;
143
  }
144
 
145
+ /* 3. CHAT INTERFACE & INPUTS */
146
+ .group, .form, .bubble-wrap {
147
+ background: rgba(15, 23, 42, 0.85) !important; /* Dark Glass */
148
+ border: 1px solid rgba(255, 255, 255, 0.3) !important;
149
+ border-radius: 15px !important;
150
+ backdrop-filter: blur(5px);
 
151
  }
152
 
153
+ /* Chat Messages */
154
  .user-message {
155
+ background: linear-gradient(135deg, #8E0E00, #1F1C18) !important; /* Deep Red */
156
+ border-left: 4px solid #D4AF37 !important; /* Gold accent */
157
+ color: white !important;
158
  }
159
+
160
  .bot-message {
161
+ background: linear-gradient(135deg, #134E5E, #1F1C18) !important; /* Deep Green */
162
+ border-left: 4px solid #71B280 !important; /* Light Green accent */
163
  color: #E0E0E0 !important;
164
  }
165
 
166
+ /* Inputs */
167
  textarea, input {
168
+ background-color: rgba(0, 0, 0, 0.6) !important;
169
+ border: 1px solid #D4AF37 !important;
170
  color: white !important;
171
+ border-radius: 20px !important;
 
 
 
172
  }
173
 
174
+ /* Buttons */
175
+ button.primary {
176
+ background: linear-gradient(to right, #D4AF37, #C5A028) !important;
177
+ color: black !important;
178
+ font-weight: bold !important;
179
+ border: none !important;
180
+ }
181
  """
182
 
183
+ # --- 5. BUILD THE UI ---
184
+ with gr.Blocks(css=christmas_css, title="Christmas Lab 2") as demo:
185
+
186
+ # HTML Header (The "Hero")
187
+ gr.HTML(
188
+ """
189
+ <div class="hero">
190
+ <div class="hero-inner">
191
+ <div class="hero-image">
192
+ <img src="https://images.unsplash.com/photo-1482517967863-00e15c9b4499?q=80&w=400&auto=format&fit=crop" alt="Christmas AI">
193
+ </div>
194
+ <div class="hero-text">
195
+ <h1>Holiday AI Assistant</h1>
196
+ <p>
197
+ Welcome to the Winter Workshop. I am powered by fine-tuned Llama models
198
+ and hot cocoa. Ask me anything, and stay frosty!
199
+ </p>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ """
204
+ )
205
+
206
+ # The Chat Interface
207
+ # Note: We pass the sliders here as 'additional_inputs' just like before
208
+ max_new_tokens_slider = gr.Slider(minimum=16, maximum=256, value=64, step=8, label="Max Response Length")
209
+ style_radio = gr.Radio(["Default", "Short answer", "Detailed explanation"], value="Detailed explanation", label="Style")
210
+
211
+ chat = gr.ChatInterface(
212
+ fn=chat_fn,
213
+ additional_inputs=[max_new_tokens_slider, style_radio],
214
+ additional_inputs_accordion="Workshop Settings",
215
+ )
216
 
217
  if __name__ == "__main__":
218
  demo.launch(allowed_paths=["."])