Noursine commited on
Commit
aa27171
Β·
verified Β·
1 Parent(s): c7ddc2d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +85 -51
app.py CHANGED
@@ -1,13 +1,7 @@
1
  """
2
  Phi-2 Chatbot Playground β€” Hugging Face Space
3
  ==============================================
4
- A Gradio-based playground for Microsoft's Phi-2 (2.7B) model.
5
- Features:
6
- - System instruction editor
7
- - Training data / few-shot examples editor
8
- - Temperature & max token controls
9
- - Chat interface with history
10
- - Clear conversation button
11
  """
12
 
13
  import gradio as gr
@@ -34,8 +28,8 @@ print("Model loaded on CPU!")
34
 
35
  def build_prompt(system_instruction: str, training_data: str, history: list, user_input: str) -> str:
36
  """
37
- Assembles a Phi-2 compatible prompt.
38
- Phi-2 was trained on the 'Instruct / Output' format.
39
  """
40
  prompt = ""
41
 
@@ -45,8 +39,14 @@ def build_prompt(system_instruction: str, training_data: str, history: list, use
45
  if training_data.strip():
46
  prompt += f"{training_data.strip()}\n\n"
47
 
48
- for human_msg, ai_msg in history:
49
- prompt += f"Instruct: {human_msg}\nOutput: {ai_msg}\n"
 
 
 
 
 
 
50
 
51
  prompt += f"Instruct: {user_input}\nOutput:"
52
  return prompt
@@ -64,11 +64,11 @@ def generate_response(
64
  repetition_penalty: float,
65
  ):
66
  if not user_input.strip():
67
- return history, history
68
 
69
  prompt = build_prompt(system_instruction, training_data, history, user_input)
70
 
71
- inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
72
  input_len = inputs["input_ids"].shape[1]
73
 
74
  with torch.no_grad():
@@ -78,7 +78,7 @@ def generate_response(
78
  temperature=float(temperature),
79
  top_p=float(top_p),
80
  repetition_penalty=float(repetition_penalty),
81
- do_sample=temperature > 0,
82
  pad_token_id=tokenizer.eos_token_id,
83
  eos_token_id=tokenizer.eos_token_id,
84
  )
@@ -86,18 +86,22 @@ def generate_response(
86
  generated_ids = output[0][input_len:]
87
  reply = tokenizer.decode(generated_ids, skip_special_tokens=True)
88
 
89
- # Clean output β€” stop at next "Instruct:" if model keeps going
90
  reply = reply.split("Instruct:")[0].strip()
91
 
92
- history = history + [[user_input, reply]]
93
- return history, history
 
 
 
 
94
 
95
 
96
  def clear_chat():
97
- return [], []
98
 
99
 
100
- # ── UI ────────────────────────────────────────────────────────────────────────
101
 
102
  DEFAULT_SYSTEM = (
103
  "You are a helpful, respectful, and honest assistant. "
@@ -111,6 +115,8 @@ Output: 2 + 2 equals 4.
111
  Instruct: What is the capital of Japan?
112
  Output: The capital of Japan is Tokyo."""
113
 
 
 
114
  with gr.Blocks(
115
  title="Phi-2 Playground",
116
  theme=gr.themes.Soft(
@@ -119,8 +125,7 @@ with gr.Blocks(
119
  font=gr.themes.GoogleFont("IBM Plex Mono"),
120
  ),
121
  css="""
122
- #chatbot { height: 480px; overflow-y: auto; }
123
- .gr-button-primary { background: #7c3aed !important; }
124
  footer { display: none !important; }
125
  .title-block { text-align: center; padding: 12px 0 4px 0; }
126
  .title-block h1 { font-size: 2rem; font-weight: 800; letter-spacing: -1px; }
@@ -128,11 +133,10 @@ with gr.Blocks(
128
  """,
129
  ) as demo:
130
 
131
- # ── Title ──
132
  gr.HTML("""
133
  <div class="title-block">
134
  <h1>Ξ¦ Phi-2 Playground</h1>
135
- <p>microsoft/phi-2 Β· 2.7B Parameters Β· Hugging Face Transformers</p>
136
  </div>
137
  """)
138
 
@@ -140,9 +144,16 @@ with gr.Blocks(
140
 
141
  with gr.Tabs():
142
 
143
- # ── Tab 1: Chat ──
144
  with gr.TabItem("πŸ’¬ Chat"):
145
- chatbot = gr.Chatbot(elem_id="chatbot", label="Conversation", bubble_full_width=False)
 
 
 
 
 
 
 
146
 
147
  with gr.Row():
148
  user_input = gr.Textbox(
@@ -150,22 +161,19 @@ with gr.Blocks(
150
  label="Your message",
151
  lines=2,
152
  scale=8,
 
153
  )
154
  send_btn = gr.Button("Send ➀", variant="primary", scale=1, min_width=80)
155
 
156
  clear_btn = gr.Button("πŸ—‘οΈ Clear Conversation", variant="secondary")
157
 
158
- gr.Markdown(
159
- "_Press **Enter** to send. Use **Shift+Enter** for a new line._",
160
- elem_id="hint",
161
- )
162
 
163
- # ── Tab 2: System & Data ──
164
  with gr.TabItem("βš™οΈ Instructions & Data"):
 
165
  gr.Markdown("### 🧠 System Instruction")
166
- gr.Markdown(
167
- "This text is prepended to every prompt to define the model's role and behavior."
168
- )
169
  system_instruction = gr.Textbox(
170
  value=DEFAULT_SYSTEM,
171
  lines=4,
@@ -176,54 +184,73 @@ with gr.Blocks(
176
  gr.Markdown("---")
177
  gr.Markdown("### πŸ“„ Few-Shot / Training Data")
178
  gr.Markdown(
179
- "Provide example `Instruct: … / Output: …` pairs to guide the model's response style."
180
- " These act as in-context few-shot examples."
181
  )
182
  training_data = gr.Textbox(
183
  value=DEFAULT_TRAINING_DATA,
184
  lines=10,
185
- label="Training / Few-Shot Examples",
186
  placeholder="Instruct: What is X?\nOutput: X is …",
187
  )
188
 
189
  with gr.Accordion("πŸ“‹ Quick Templates", open=False):
190
- gr.Markdown("Click a template to load it into the Training Data box.")
191
  with gr.Row():
192
- tpl_qa = gr.Button("Q&A")
193
- tpl_code = gr.Button("Code Assistant")
194
  tpl_summary = gr.Button("Summarizer")
195
 
196
  tpl_qa.click(
197
- fn=lambda: "Instruct: What is the boiling point of water?\nOutput: Water boils at 100Β°C (212Β°F) at sea level.\n\nInstruct: Who wrote Romeo and Juliet?\nOutput: Romeo and Juliet was written by William Shakespeare.",
 
 
 
 
 
198
  outputs=training_data,
199
  )
200
  tpl_code.click(
201
- fn=lambda: "Instruct: Write a Python function to check if a number is prime.\nOutput: def is_prime(n):\n if n < 2: return False\n for i in range(2, int(n**0.5)+1):\n if n % i == 0: return False\n return True\n\nInstruct: How do I reverse a list in Python?\nOutput: You can reverse a list using list.reverse() in-place or list[::-1] to get a new reversed list.",
 
 
 
 
 
 
 
 
 
202
  outputs=training_data,
203
  )
204
  tpl_summary.click(
205
- fn=lambda: "Instruct: Summarize the following in one sentence.\nText: The Amazon rainforest is the world's largest tropical rainforest, covering much of northwestern Brazil.\nOutput: The Amazon rainforest is the world's largest tropical rainforest, located mainly in Brazil.",
 
 
 
 
206
  outputs=training_data,
207
  )
208
 
209
- # ── Tab 3: Parameters ──
210
  with gr.TabItem("πŸŽ›οΈ Parameters"):
 
211
  gr.Markdown("### Generation Parameters")
212
 
213
  temperature = gr.Slider(
214
  0.01, 2.0, value=0.7, step=0.01,
215
  label="Temperature",
216
- info="Higher = more creative / random. Lower = more deterministic.",
217
  )
218
  max_new_tokens = gr.Slider(
219
- 32, 1024, value=256, step=16,
220
  label="Max New Tokens",
221
- info="Maximum number of tokens the model will generate.",
222
  )
223
  top_p = gr.Slider(
224
  0.1, 1.0, value=0.95, step=0.01,
225
  label="Top-p (Nucleus Sampling)",
226
- info="Keeps only the top probability mass tokens.",
227
  )
228
  repetition_penalty = gr.Slider(
229
  1.0, 2.0, value=1.1, step=0.05,
@@ -234,6 +261,7 @@ with gr.Blocks(
234
  gr.Markdown("---")
235
  gr.Markdown("""
236
  **Model Details**
 
237
  | Property | Value |
238
  |---|---|
239
  | Model | `microsoft/phi-2` |
@@ -241,6 +269,7 @@ with gr.Blocks(
241
  | Architecture | Transformer Decoder |
242
  | Context Length | 2048 tokens |
243
  | License | MIT |
 
244
 
245
  [πŸ“„ Model Card on Hugging Face](https://huggingface.co/microsoft/phi-2)
246
  """)
@@ -252,15 +281,20 @@ with gr.Blocks(
252
  system_instruction, training_data,
253
  temperature, max_new_tokens, top_p, repetition_penalty,
254
  ]
255
- gen_outputs = [chatbot, state]
 
 
 
256
 
257
  send_btn.click(generate_response, inputs=gen_inputs, outputs=gen_outputs).then(
258
- lambda: "", outputs=user_input
259
  )
260
  user_input.submit(generate_response, inputs=gen_inputs, outputs=gen_outputs).then(
261
- lambda: "", outputs=user_input
 
 
 
262
  )
263
- clear_btn.click(clear_chat, outputs=[chatbot, state])
264
 
265
 
266
  # ── Launch ────────────────────────────────────────────────────────────────────
 
1
  """
2
  Phi-2 Chatbot Playground β€” Hugging Face Space
3
  ==============================================
4
+ Compatible with Gradio 6.x (messages format) + CPU deployment.
 
 
 
 
 
 
5
  """
6
 
7
  import gradio as gr
 
28
 
29
  def build_prompt(system_instruction: str, training_data: str, history: list, user_input: str) -> str:
30
  """
31
+ Assembles a Phi-2 compatible prompt from Gradio 6 messages format.
32
+ history = [{"role": "user"|"assistant", "content": "..."}]
33
  """
34
  prompt = ""
35
 
 
39
  if training_data.strip():
40
  prompt += f"{training_data.strip()}\n\n"
41
 
42
+ # Pair up messages from history
43
+ i = 0
44
+ while i < len(history) - 1:
45
+ if history[i]["role"] == "user" and history[i+1]["role"] == "assistant":
46
+ prompt += f"Instruct: {history[i]['content']}\nOutput: {history[i+1]['content']}\n"
47
+ i += 2
48
+ else:
49
+ i += 1
50
 
51
  prompt += f"Instruct: {user_input}\nOutput:"
52
  return prompt
 
64
  repetition_penalty: float,
65
  ):
66
  if not user_input.strip():
67
+ return history, ""
68
 
69
  prompt = build_prompt(system_instruction, training_data, history, user_input)
70
 
71
+ inputs = tokenizer(prompt, return_tensors="pt")
72
  input_len = inputs["input_ids"].shape[1]
73
 
74
  with torch.no_grad():
 
78
  temperature=float(temperature),
79
  top_p=float(top_p),
80
  repetition_penalty=float(repetition_penalty),
81
+ do_sample=temperature > 0.01,
82
  pad_token_id=tokenizer.eos_token_id,
83
  eos_token_id=tokenizer.eos_token_id,
84
  )
 
86
  generated_ids = output[0][input_len:]
87
  reply = tokenizer.decode(generated_ids, skip_special_tokens=True)
88
 
89
+ # Stop at next "Instruct:" if model keeps generating
90
  reply = reply.split("Instruct:")[0].strip()
91
 
92
+ # Gradio 6 messages format
93
+ history = history + [
94
+ {"role": "user", "content": user_input},
95
+ {"role": "assistant", "content": reply},
96
+ ]
97
+ return history, ""
98
 
99
 
100
  def clear_chat():
101
+ return [], ""
102
 
103
 
104
+ # ── Defaults ──────────────────────────────────────────────────────────────────
105
 
106
  DEFAULT_SYSTEM = (
107
  "You are a helpful, respectful, and honest assistant. "
 
115
  Instruct: What is the capital of Japan?
116
  Output: The capital of Japan is Tokyo."""
117
 
118
+ # ── UI ────────────────────────────────────────────────────────────────────────
119
+
120
  with gr.Blocks(
121
  title="Phi-2 Playground",
122
  theme=gr.themes.Soft(
 
125
  font=gr.themes.GoogleFont("IBM Plex Mono"),
126
  ),
127
  css="""
128
+ #chatbot { height: 460px; overflow-y: auto; }
 
129
  footer { display: none !important; }
130
  .title-block { text-align: center; padding: 12px 0 4px 0; }
131
  .title-block h1 { font-size: 2rem; font-weight: 800; letter-spacing: -1px; }
 
133
  """,
134
  ) as demo:
135
 
 
136
  gr.HTML("""
137
  <div class="title-block">
138
  <h1>Ξ¦ Phi-2 Playground</h1>
139
+ <p>microsoft/phi-2 Β· 2.7B Parameters Β· CPU Β· Gradio 6</p>
140
  </div>
141
  """)
142
 
 
144
 
145
  with gr.Tabs():
146
 
147
+ # ── Tab 1: Chat ───────────────────────────────────────────────────���───
148
  with gr.TabItem("πŸ’¬ Chat"):
149
+
150
+ chatbot = gr.Chatbot(
151
+ elem_id="chatbot",
152
+ label="Conversation",
153
+ type="messages", # Gradio 6 messages format
154
+ bubble_full_width=False,
155
+ show_label=False,
156
+ )
157
 
158
  with gr.Row():
159
  user_input = gr.Textbox(
 
161
  label="Your message",
162
  lines=2,
163
  scale=8,
164
+ show_label=False,
165
  )
166
  send_btn = gr.Button("Send ➀", variant="primary", scale=1, min_width=80)
167
 
168
  clear_btn = gr.Button("πŸ—‘οΈ Clear Conversation", variant="secondary")
169
 
170
+ gr.Markdown("_⚠️ CPU mode: responses may take 1–3 minutes. Please be patient!_")
 
 
 
171
 
172
+ # ── Tab 2: Instructions & Data ────────────────────────────────────────
173
  with gr.TabItem("βš™οΈ Instructions & Data"):
174
+
175
  gr.Markdown("### 🧠 System Instruction")
176
+ gr.Markdown("Prepended to every prompt β€” defines the assistant's persona and behavior.")
 
 
177
  system_instruction = gr.Textbox(
178
  value=DEFAULT_SYSTEM,
179
  lines=4,
 
184
  gr.Markdown("---")
185
  gr.Markdown("### πŸ“„ Few-Shot / Training Data")
186
  gr.Markdown(
187
+ "Add `Instruct: … / Output: …` example pairs here to guide the model's style. "
188
+ "These act as in-context few-shot examples injected before your message."
189
  )
190
  training_data = gr.Textbox(
191
  value=DEFAULT_TRAINING_DATA,
192
  lines=10,
193
+ label="Few-Shot Examples",
194
  placeholder="Instruct: What is X?\nOutput: X is …",
195
  )
196
 
197
  with gr.Accordion("πŸ“‹ Quick Templates", open=False):
198
+ gr.Markdown("Click a template below to load it into the few-shot box.")
199
  with gr.Row():
200
+ tpl_qa = gr.Button("Q&A")
201
+ tpl_code = gr.Button("Code Assistant")
202
  tpl_summary = gr.Button("Summarizer")
203
 
204
  tpl_qa.click(
205
+ fn=lambda: (
206
+ "Instruct: What is the boiling point of water?\n"
207
+ "Output: Water boils at 100Β°C (212Β°F) at sea level.\n\n"
208
+ "Instruct: Who wrote Romeo and Juliet?\n"
209
+ "Output: Romeo and Juliet was written by William Shakespeare."
210
+ ),
211
  outputs=training_data,
212
  )
213
  tpl_code.click(
214
+ fn=lambda: (
215
+ "Instruct: Write a Python function to check if a number is prime.\n"
216
+ "Output: def is_prime(n):\n"
217
+ " if n < 2: return False\n"
218
+ " for i in range(2, int(n**0.5)+1):\n"
219
+ " if n % i == 0: return False\n"
220
+ " return True\n\n"
221
+ "Instruct: How do I reverse a list in Python?\n"
222
+ "Output: Use list[::-1] to get a reversed copy, or list.reverse() to reverse in place."
223
+ ),
224
  outputs=training_data,
225
  )
226
  tpl_summary.click(
227
+ fn=lambda: (
228
+ "Instruct: Summarize the following in one sentence.\n"
229
+ "Text: The Amazon rainforest covers much of northwestern Brazil and is the world's largest tropical rainforest.\n"
230
+ "Output: The Amazon rainforest is the world's largest tropical rainforest, located mainly in Brazil."
231
+ ),
232
  outputs=training_data,
233
  )
234
 
235
+ # ── Tab 3: Parameters ─────────────────────────────────────────────────
236
  with gr.TabItem("πŸŽ›οΈ Parameters"):
237
+
238
  gr.Markdown("### Generation Parameters")
239
 
240
  temperature = gr.Slider(
241
  0.01, 2.0, value=0.7, step=0.01,
242
  label="Temperature",
243
+ info="Higher = more creative. Lower = more focused.",
244
  )
245
  max_new_tokens = gr.Slider(
246
+ 32, 512, value=200, step=16,
247
  label="Max New Tokens",
248
+ info="Max tokens to generate. Keep low on CPU for faster responses.",
249
  )
250
  top_p = gr.Slider(
251
  0.1, 1.0, value=0.95, step=0.01,
252
  label="Top-p (Nucleus Sampling)",
253
+ info="Restricts sampling to top probability mass.",
254
  )
255
  repetition_penalty = gr.Slider(
256
  1.0, 2.0, value=1.1, step=0.05,
 
261
  gr.Markdown("---")
262
  gr.Markdown("""
263
  **Model Details**
264
+
265
  | Property | Value |
266
  |---|---|
267
  | Model | `microsoft/phi-2` |
 
269
  | Architecture | Transformer Decoder |
270
  | Context Length | 2048 tokens |
271
  | License | MIT |
272
+ | Runtime | CPU (float32) |
273
 
274
  [πŸ“„ Model Card on Hugging Face](https://huggingface.co/microsoft/phi-2)
275
  """)
 
281
  system_instruction, training_data,
282
  temperature, max_new_tokens, top_p, repetition_penalty,
283
  ]
284
+ gen_outputs = [state, user_input]
285
+
286
+ def sync_chatbot(history, _user_input):
287
+ return history
288
 
289
  send_btn.click(generate_response, inputs=gen_inputs, outputs=gen_outputs).then(
290
+ fn=lambda h: h, inputs=state, outputs=chatbot
291
  )
292
  user_input.submit(generate_response, inputs=gen_inputs, outputs=gen_outputs).then(
293
+ fn=lambda h: h, inputs=state, outputs=chatbot
294
+ )
295
+ clear_btn.click(clear_chat, outputs=[state, user_input]).then(
296
+ fn=lambda h: h, inputs=state, outputs=chatbot
297
  )
 
298
 
299
 
300
  # ── Launch ────────────────────────────────────────────────────────────────────