burtenshaw commited on
Commit
4e3d86a
·
unverified ·
2 Parent(s): 294ddf1 62aa801

Merge branch 'main' into patch-1

Browse files
Files changed (1) hide show
  1. app/app.py +158 -61
app/app.py CHANGED
@@ -14,37 +14,66 @@ from huggingface_hub import InferenceClient
14
  from pandas import DataFrame
15
 
16
  LANGUAGES: dict[str, str] = {
17
- "English": "You are a helpful assistant that speaks English.",
18
- "Spanish": "Tu eres un asistente útil que habla español.",
 
 
 
 
 
 
 
 
 
19
  "Hebrew": " אתה עוזר טוב ומועיל שמדבר בעברית ועונה בעברית.",
20
- "Dutch": "Je bent een handige assistent die Nederlands spreekt.",
21
- "Italian": "Tu sei un assistente utile che parla italiano.",
22
- "French": "Tu es un assistant utile qui parle français.",
23
- "German": "Du bist ein hilfreicher Assistent, der Deutsch spricht.",
24
- "Portuguese": "Você é um assistente útil que fala português.",
25
- "Russian": "Ты полезный помощник, который говорит по-русски.",
26
- "Chinese": "你是一个有用的助手,会说中文。",
27
- "Japanese": "あなたは役立つ助け役で、日本語を話します。",
28
- "Korean": "당신은 유용한 도우미이며 한국어를 말합니다.",
29
  }
30
 
31
- client = InferenceClient(
32
- token=os.getenv("HF_TOKEN"),
33
- model=(
34
- os.getenv("MODEL", "meta-llama/Llama-3.2-11B-Vision-Instruct")
35
- if not os.getenv("BASE_URL")
36
- else None
37
- ),
38
- base_url=os.getenv("BASE_URL"),
39
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
 
42
  def add_user_message(history, message):
43
- for x in message["files"]:
44
- history.append({"role": "user", "content": {"path": x}})
45
- if message["text"] is not None:
46
- history.append({"role": "user", "content": message["text"]})
47
- return history, gr.MultimodalTextbox(value=None, interactive=False)
 
 
 
48
 
49
 
50
  def format_system_message(language: str, history: list):
@@ -128,7 +157,11 @@ def _process_rating(rating) -> int:
128
 
129
 
130
  def add_fake_like_data(
131
- history: list, session_id: str, language: str, liked: bool = False
 
 
 
 
132
  ) -> None:
133
  data = {
134
  "index": len(history) - 1,
@@ -138,17 +171,25 @@ def add_fake_like_data(
138
  _, dataframe = wrangle_like_data(
139
  gr.LikeData(target=None, data=data), history.copy()
140
  )
141
- submit_conversation(dataframe, session_id, language)
 
 
 
 
 
142
 
143
 
144
- def respond_system_message(
145
- history: list, temperature: Optional[float] = None, seed: Optional[int] = None
 
 
 
146
  ) -> list: # -> list:
147
  """Respond to the user message with a system message
148
 
149
  Return the history with the new message"""
150
  messages = format_history_as_messages(history)
151
- response = client.chat.completions.create(
152
  messages=messages,
153
  max_tokens=2000,
154
  stream=False,
@@ -187,7 +228,11 @@ def wrangle_like_data(x: gr.LikeData, history) -> DataFrame:
187
  if isinstance(message, gr.ChatMessage):
188
  message = message.__dict__
189
  if idx == liked_index:
190
- message["metadata"] = {"title": "liked" if x.liked else "disliked"}
 
 
 
 
191
  if not isinstance(message["metadata"], dict):
192
  message["metadata"] = message["metadata"].__dict__
193
  rating = message["metadata"].get("title")
@@ -221,7 +266,12 @@ def wrangle_like_data(x: gr.LikeData, history) -> DataFrame:
221
 
222
 
223
  def wrangle_edit_data(
224
- x: gr.EditData, history: list, dataframe: DataFrame, session_id: str, language: str
 
 
 
 
 
225
  ) -> list:
226
  """Edit the conversation and add negative feedback if assistant message is edited, otherwise regenerate the message
227
 
@@ -237,20 +287,41 @@ def wrangle_edit_data(
237
 
238
  if history[index]["role"] == "user":
239
  # Add feedback on original and corrected message
240
- add_fake_like_data(history[: index + 2], session_id, language, liked=True)
241
  add_fake_like_data(
242
- history[: index + 1] + [original_message], session_id, language
 
 
 
 
243
  )
244
- history = respond_system_message(
245
- history[: index + 1],
 
 
 
 
 
 
 
246
  temperature=random.randint(1, 100) / 100,
247
  seed=random.randint(0, 1000000),
248
  )
249
  return history
250
  else:
251
  # Add feedback on original and corrected message
252
- add_fake_like_data(history[: index + 1], session_id, language, liked=True)
253
- add_fake_like_data(history[:index] + [original_message], session_id, language)
 
 
 
 
 
 
 
 
 
 
 
254
  history = history[: index + 1]
255
  # add chosen and rejected options
256
  history[-1]["options"] = [
@@ -261,23 +332,34 @@ def wrangle_edit_data(
261
 
262
 
263
  def wrangle_retry_data(
264
- x: gr.RetryData, history: list, dataframe: DataFrame, session_id: str, language: str
 
 
 
 
 
265
  ) -> list:
266
  """Respond to the user message with a system message and add negative feedback on the original message
267
 
268
  Return the history with the new message"""
269
- add_fake_like_data(history, session_id, language)
 
 
 
 
 
270
 
271
  # Return the history without a new message
272
- history = respond_system_message(
273
- history[:-1],
 
274
  temperature=random.randint(1, 100) / 100,
275
  seed=random.randint(0, 1000000),
276
  )
277
  return history, update_dataframe(dataframe, history)
278
 
279
 
280
- def submit_conversation(dataframe, session_id, language):
281
  """ "Submit the conversation to dataset repo"""
282
  if dataframe.empty or len(dataframe) < 2:
283
  gr.Info("No feedback to submit.")
@@ -290,11 +372,10 @@ def submit_conversation(dataframe, session_id, language):
290
  "conversation": conversation,
291
  "timestamp": datetime.now().isoformat(),
292
  "session_id": session_id,
293
- "conversation_id": str(uuid.uuid4()),
294
  "language": language,
295
  }
296
  save_feedback(input_object=conversation_data)
297
- gr.Info("Submitted your feedback!")
298
  return (gr.Dataframe(value=None, interactive=False), [])
299
 
300
 
@@ -317,7 +398,9 @@ with gr.Blocks(css=css) as demo:
317
 
318
  with gr.Accordion("Explanation") as explanation:
319
  gr.Markdown(f"""
320
- FeeL is a collaboration between Hugging Face and MIT. It is a community-driven project to provide a real-time feedback loop for VLMs, where your feedback is continuously used to train the model. The [dataset](https://huggingface.co/datasets/{scheduler.repo_id}) and [code](https://github.com/huggingface/feel) are public.
 
 
321
 
322
  Start by selecting your language, chat with the model with text and images and provide feedback in different ways.
323
 
@@ -325,7 +408,7 @@ with gr.Blocks(css=css) as demo:
325
  - 👍/👎 Like or dislike a message
326
  - 🔄 Regenerate a message
327
 
328
- Some feedback is automatically submitted allowing you to continue chatting, but you can also submit and reset the conversation by clicking "💾 Submit conversation" (under the chat) or trash the conversation by clicking "🗑️" (upper right corner).
329
  """)
330
  language = gr.Dropdown(
331
  choices=list(LANGUAGES.keys()), label="Language", interactive=True
@@ -337,6 +420,12 @@ with gr.Blocks(css=css) as demo:
337
  visible=False,
338
  )
339
 
 
 
 
 
 
 
340
  chatbot = gr.Chatbot(
341
  elem_id="chatbot",
342
  editable="all",
@@ -351,19 +440,17 @@ with gr.Blocks(css=css) as demo:
351
  feedback_options=["Like", "Dislike"],
352
  )
353
 
354
- chat_input = gr.MultimodalTextbox(
355
  interactive=True,
356
- file_count="multiple",
357
  placeholder="Enter message or upload file...",
358
  show_label=False,
359
  submit_btn=True,
360
  )
361
 
362
- dataframe = gr.Dataframe(wrap=True, label="Collected feedback")
 
363
 
364
- submit_btn = gr.Button(
365
- value="💾 Submit conversation",
366
- )
367
 
368
  ##############################
369
  # Deal with feedback
@@ -379,34 +466,46 @@ with gr.Blocks(css=css) as demo:
379
  fn=add_user_message,
380
  inputs=[chatbot, chat_input],
381
  outputs=[chatbot, chat_input],
382
- ).then(respond_system_message, chatbot, chatbot, api_name="bot_response").then(
383
  lambda: gr.Textbox(interactive=True), None, [chat_input]
384
- ).then(update_dataframe, inputs=[dataframe, chatbot], outputs=[dataframe])
 
 
 
385
 
386
  chatbot.like(
387
  fn=wrangle_like_data,
388
  inputs=[chatbot],
389
  outputs=[chatbot, dataframe],
390
  like_user_message=False,
 
 
 
391
  )
392
 
393
  chatbot.retry(
394
  fn=wrangle_retry_data,
395
- inputs=[chatbot, dataframe, session_id, language],
396
  outputs=[chatbot, dataframe],
397
  )
398
 
399
  chatbot.edit(
400
  fn=wrangle_edit_data,
401
- inputs=[chatbot, dataframe, session_id, language],
402
  outputs=[chatbot],
403
  ).then(update_dataframe, inputs=[dataframe, chatbot], outputs=[dataframe])
404
 
405
- submit_btn.click(
 
406
  fn=submit_conversation,
407
- inputs=[dataframe, session_id, language],
408
  outputs=[dataframe, chatbot],
 
 
 
 
409
  )
 
410
  demo.load(
411
  lambda: str(uuid.uuid4()),
412
  inputs=[],
@@ -414,5 +513,3 @@ with gr.Blocks(css=css) as demo:
414
  )
415
 
416
  demo.launch()
417
-
418
- # /private/var/folders/9t/msy700h16jz3q35qvg4z1ln40000gn/T/gradio/a5013b9763ad9f2192254540fee226539fbcd1382cbc2317b916aef469bb01b9/Screenshot 2025-01-13 at 08.02.26.png
 
14
  from pandas import DataFrame
15
 
16
  LANGUAGES: dict[str, str] = {
17
+ "English": "You are a helpful assistant. Always respond to requests in fluent and natural English, regardless of the language used by the user.",
18
+ "Dutch": "Je bent een behulpzame assistent die uitsluitend in het Nederlands communiceert. Beantwoord alle vragen en verzoeken in vloeiend en natuurlijk Nederlands, ongeacht de taal waarin de gebruiker schrijft.",
19
+ "Italian": "Sei un assistente utile e rispondi sempre in italiano in modo naturale e fluente, indipendentemente dalla lingua utilizzata dall'utente.",
20
+ "Spanish": "Eres un asistente útil que siempre responde en español de manera fluida y natural, independientemente del idioma utilizado por el usuario.",
21
+ "French": "Tu es un assistant utile qui répond toujours en français de manière fluide et naturelle, quelle que soit la langue utilisée par l'utilisateur.",
22
+ "German": "Du bist ein hilfreicher Assistent, der stets auf Deutsch in einer natürlichen und fließenden Weise antwortet, unabhängig von der Sprache des Benutzers.",
23
+ "Portuguese": "Você é um assistente útil que sempre responde em português de forma natural e fluente, independentemente do idioma utilizado pelo usuário.",
24
+ "Russian": "Ты полезный помощник, который всегда отвечает на русском языке плавно и естественно, независимо от языка пользователя.",
25
+ "Chinese": "你是一个有用的助手,总是用流畅自然的中文回答问题,无论用户使用哪种语言。",
26
+ "Japanese": "あなたは役に立つアシスタントであり、常に流暢で自然な日本語で応答します。ユーザーが使用する言語に関係なく、日本語で対応してください。",
27
+ "Korean": "당신은 유용한 도우미이며, 항상 유창하고 자연스러운 한국어로 응답합니다. 사용자가 어떤 언어를 사용하든 한국어로 대답하세요.",
28
  "Hebrew": " אתה עוזר טוב ומועיל שמדבר בעברית ועונה בעברית.",
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
+
32
+ BASE_MODEL = os.getenv("MODEL", "meta-llama/Llama-3.2-11B-Vision-Instruct")
33
+
34
+
35
+ def create_inference_client(
36
+ model: Optional[str] = None, base_url: Optional[str] = None
37
+ ) -> InferenceClient:
38
+ """Create an InferenceClient instance with the given model or environment settings.
39
+
40
+ Args:
41
+ model: Optional model identifier to use. If not provided, will use environment settings.
42
+
43
+ Returns:
44
+ InferenceClient: Configured client instance
45
+ """
46
+ return InferenceClient(
47
+ token=os.getenv("HF_TOKEN"),
48
+ model=model if model else (BASE_MODEL if not base_url else None),
49
+ base_url=base_url,
50
+ )
51
+
52
+
53
+ LANGUAGES_TO_CLIENT = {
54
+ "English": create_inference_client(),
55
+ "Dutch": create_inference_client(),
56
+ "Italian": create_inference_client(),
57
+ "Spanish": create_inference_client(),
58
+ "French": create_inference_client(),
59
+ "German": create_inference_client(),
60
+ "Portuguese": create_inference_client(),
61
+ "Russian": create_inference_client(),
62
+ "Chinese": create_inference_client(),
63
+ "Japanese": create_inference_client(),
64
+ "Korean": create_inference_client(),
65
+ }
66
 
67
 
68
  def add_user_message(history, message):
69
+ if isinstance(message, dict) and "files" in message:
70
+ for x in message["files"]:
71
+ history.append({"role": "user", "content": {"path": x}})
72
+ if message["text"] is not None:
73
+ history.append({"role": "user", "content": message["text"]})
74
+ else:
75
+ history.append({"role": "user", "content": message})
76
+ return history, gr.Textbox(value=None, interactive=False)
77
 
78
 
79
  def format_system_message(language: str, history: list):
 
157
 
158
 
159
  def add_fake_like_data(
160
+ history: list,
161
+ conversation_id: str,
162
+ session_id: str,
163
+ language: str,
164
+ liked: bool = False,
165
  ) -> None:
166
  data = {
167
  "index": len(history) - 1,
 
171
  _, dataframe = wrangle_like_data(
172
  gr.LikeData(target=None, data=data), history.copy()
173
  )
174
+ submit_conversation(
175
+ dataframe=dataframe,
176
+ conversation_id=conversation_id,
177
+ session_id=session_id,
178
+ language=language,
179
+ )
180
 
181
 
182
+ def respond(
183
+ history: list,
184
+ language: str,
185
+ temperature: Optional[float] = None,
186
+ seed: Optional[int] = None,
187
  ) -> list: # -> list:
188
  """Respond to the user message with a system message
189
 
190
  Return the history with the new message"""
191
  messages = format_history_as_messages(history)
192
+ response = LANGUAGES_TO_CLIENT[language].chat.completions.create(
193
  messages=messages,
194
  max_tokens=2000,
195
  stream=False,
 
228
  if isinstance(message, gr.ChatMessage):
229
  message = message.__dict__
230
  if idx == liked_index:
231
+ if x.liked is True:
232
+ message["metadata"] = {"title": "liked"}
233
+ elif x.liked is False:
234
+ message["metadata"] = {"title": "disliked"}
235
+
236
  if not isinstance(message["metadata"], dict):
237
  message["metadata"] = message["metadata"].__dict__
238
  rating = message["metadata"].get("title")
 
266
 
267
 
268
  def wrangle_edit_data(
269
+ x: gr.EditData,
270
+ history: list,
271
+ dataframe: DataFrame,
272
+ conversation_id: str,
273
+ session_id: str,
274
+ language: str,
275
  ) -> list:
276
  """Edit the conversation and add negative feedback if assistant message is edited, otherwise regenerate the message
277
 
 
287
 
288
  if history[index]["role"] == "user":
289
  # Add feedback on original and corrected message
 
290
  add_fake_like_data(
291
+ history=history[: index + 2],
292
+ conversation_id=conversation_id,
293
+ session_id=session_id,
294
+ language=language,
295
+ liked=True,
296
  )
297
+ add_fake_like_data(
298
+ history=history[: index + 1] + [original_message],
299
+ conversation_id=conversation_id,
300
+ session_id=session_id,
301
+ language=language,
302
+ )
303
+ history = respond(
304
+ history=history[: index + 1],
305
+ language=language,
306
  temperature=random.randint(1, 100) / 100,
307
  seed=random.randint(0, 1000000),
308
  )
309
  return history
310
  else:
311
  # Add feedback on original and corrected message
312
+ add_fake_like_data(
313
+ history=history[: index + 1],
314
+ conversation_id=conversation_id,
315
+ session_id=session_id,
316
+ language=language,
317
+ liked=True,
318
+ )
319
+ add_fake_like_data(
320
+ history=history[:index] + [original_message],
321
+ conversation_id=conversation_id,
322
+ session_id=session_id,
323
+ language=language,
324
+ )
325
  history = history[: index + 1]
326
  # add chosen and rejected options
327
  history[-1]["options"] = [
 
332
 
333
 
334
  def wrangle_retry_data(
335
+ x: gr.RetryData,
336
+ history: list,
337
+ dataframe: DataFrame,
338
+ conversation_id: str,
339
+ session_id: str,
340
+ language: str,
341
  ) -> list:
342
  """Respond to the user message with a system message and add negative feedback on the original message
343
 
344
  Return the history with the new message"""
345
+ add_fake_like_data(
346
+ history=history,
347
+ conversation_id=conversation_id,
348
+ session_id=session_id,
349
+ language=language,
350
+ )
351
 
352
  # Return the history without a new message
353
+ history = respond(
354
+ history=history[:-1],
355
+ language=language,
356
  temperature=random.randint(1, 100) / 100,
357
  seed=random.randint(0, 1000000),
358
  )
359
  return history, update_dataframe(dataframe, history)
360
 
361
 
362
+ def submit_conversation(dataframe, conversation_id, session_id, language):
363
  """ "Submit the conversation to dataset repo"""
364
  if dataframe.empty or len(dataframe) < 2:
365
  gr.Info("No feedback to submit.")
 
372
  "conversation": conversation,
373
  "timestamp": datetime.now().isoformat(),
374
  "session_id": session_id,
375
+ "conversation_id": conversation_id,
376
  "language": language,
377
  }
378
  save_feedback(input_object=conversation_data)
 
379
  return (gr.Dataframe(value=None, interactive=False), [])
380
 
381
 
 
398
 
399
  with gr.Accordion("Explanation") as explanation:
400
  gr.Markdown(f"""
401
+ FeeL is a collaboration between Hugging Face and MIT.
402
+ It is a community-driven project to provide a real-time feedback loop for VLMs, where your feedback is continuously used to fine-tune the underlying models.
403
+ The [dataset](https://huggingface.co/datasets/{scheduler.repo_id}), [code](https://github.com/huggingface/feel) and [models](https://huggingface.co/collections/feel-fl/feel-models-67a9b6ef0fdd554315e295e8) are public.
404
 
405
  Start by selecting your language, chat with the model with text and images and provide feedback in different ways.
406
 
 
408
  - 👍/👎 Like or dislike a message
409
  - 🔄 Regenerate a message
410
 
411
+ Feedback is automatically submitted allowing you to continue chatting, but you can also submit and reset the conversation by clicking "💾 Submit conversation" (under the chat) or trash the conversation by clicking "🗑️" (upper right corner).
412
  """)
413
  language = gr.Dropdown(
414
  choices=list(LANGUAGES.keys()), label="Language", interactive=True
 
420
  visible=False,
421
  )
422
 
423
+ conversation_id = gr.Textbox(
424
+ interactive=False,
425
+ value=str(uuid.uuid4()),
426
+ visible=False,
427
+ )
428
+
429
  chatbot = gr.Chatbot(
430
  elem_id="chatbot",
431
  editable="all",
 
440
  feedback_options=["Like", "Dislike"],
441
  )
442
 
443
+ chat_input = gr.Textbox(
444
  interactive=True,
 
445
  placeholder="Enter message or upload file...",
446
  show_label=False,
447
  submit_btn=True,
448
  )
449
 
450
+ with gr.Accordion("Collected feedback", open=False):
451
+ dataframe = gr.Dataframe(wrap=True, label="Collected feedback")
452
 
453
+ submit_btn = gr.Button(value="💾 Submit conversation", visible=False)
 
 
454
 
455
  ##############################
456
  # Deal with feedback
 
466
  fn=add_user_message,
467
  inputs=[chatbot, chat_input],
468
  outputs=[chatbot, chat_input],
469
+ ).then(respond, inputs=[chatbot, language], outputs=[chatbot]).then(
470
  lambda: gr.Textbox(interactive=True), None, [chat_input]
471
+ ).then(update_dataframe, inputs=[dataframe, chatbot], outputs=[dataframe]).then(
472
+ submit_conversation,
473
+ inputs=[dataframe, conversation_id, session_id, language],
474
+ )
475
 
476
  chatbot.like(
477
  fn=wrangle_like_data,
478
  inputs=[chatbot],
479
  outputs=[chatbot, dataframe],
480
  like_user_message=False,
481
+ ).then(
482
+ submit_conversation,
483
+ inputs=[dataframe, conversation_id, session_id, language],
484
  )
485
 
486
  chatbot.retry(
487
  fn=wrangle_retry_data,
488
+ inputs=[chatbot, dataframe, conversation_id, session_id, language],
489
  outputs=[chatbot, dataframe],
490
  )
491
 
492
  chatbot.edit(
493
  fn=wrangle_edit_data,
494
+ inputs=[chatbot, dataframe, conversation_id, session_id, language],
495
  outputs=[chatbot],
496
  ).then(update_dataframe, inputs=[dataframe, chatbot], outputs=[dataframe])
497
 
498
+ gr.on(
499
+ triggers=[submit_btn.click, chatbot.clear],
500
  fn=submit_conversation,
501
+ inputs=[dataframe, conversation_id, session_id, language],
502
  outputs=[dataframe, chatbot],
503
+ ).then(
504
+ fn=lambda x: str(uuid.uuid4()),
505
+ inputs=[conversation_id],
506
+ outputs=[conversation_id],
507
  )
508
+
509
  demo.load(
510
  lambda: str(uuid.uuid4()),
511
  inputs=[],
 
513
  )
514
 
515
  demo.launch()