LukasHug commited on
Commit
6262027
1 Parent(s): e992a5c

Delete gradio_web_server.py

Browse files
Files changed (1) hide show
  1. gradio_web_server.py +0 -508
gradio_web_server.py DELETED
@@ -1,508 +0,0 @@
1
- import argparse
2
- import datetime
3
- import json
4
- import os
5
- import time
6
-
7
- import gradio as gr
8
- import requests
9
-
10
- from llava.conversation import (default_conversation, conv_templates,
11
- SeparatorStyle)
12
- from llava.constants import LOGDIR
13
- from llava.utils import (build_logger, server_error_msg,
14
- violates_moderation, moderation_msg)
15
- import hashlib
16
-
17
- from taxonomy import wrap_taxonomy, default_taxonomy
18
-
19
-
20
- def clear_conv(conv):
21
- conv.messages = []
22
- return conv
23
-
24
-
25
- logger = build_logger("gradio_web_server", "gradio_web_server.log")
26
-
27
- headers = {"User-Agent": "LLaVA Client"}
28
-
29
- no_change_btn = gr.Button()
30
- enable_btn = gr.Button(interactive=True)
31
- disable_btn = gr.Button(interactive=False)
32
-
33
- priority = {
34
- "LlavaGuard-7B": "aaaaaaa",
35
- "LlavaGuard-13B": "aaaaaab",
36
- "LlavaGuard-34B": "aaaaaac",
37
- }
38
-
39
-
40
- def get_conv_log_filename():
41
- t = datetime.datetime.now()
42
- name = os.path.join(LOGDIR, f"{t.year}-{t.month:02d}-{t.day:02d}-conv.json")
43
- return name
44
-
45
-
46
- def get_model_list():
47
- ret = requests.post(args.controller_url + "/refresh_all_workers")
48
- assert ret.status_code == 200
49
- ret = requests.post(args.controller_url + "/list_models")
50
- logger.info(f"get_model_list: {ret.json()}")
51
- models = ret.json()["models"]
52
- models.sort(key=lambda x: priority.get(x, x))
53
- logger.info(f"Models: {models}")
54
- return models
55
-
56
-
57
- get_window_url_params = """
58
- function() {
59
- const params = new URLSearchParams(window.location.search);
60
- url_params = Object.fromEntries(params);
61
- console.log(url_params);
62
- return url_params;
63
- }
64
- """
65
-
66
-
67
- def load_demo(url_params, request: gr.Request):
68
- logger.info(f"load_demo. ip: {request.client.host}. params: {url_params}")
69
-
70
- dropdown_update = gr.Dropdown(visible=True)
71
- if "model" in url_params:
72
- model = url_params["model"]
73
- if model in models:
74
- dropdown_update = gr.Dropdown(value=model, visible=True)
75
-
76
- state = default_conversation.copy()
77
- return state, dropdown_update
78
-
79
-
80
- def load_demo_refresh_model_list(request: gr.Request):
81
- logger.info(f"load_demo. ip: {request.client.host}")
82
- models = get_model_list()
83
- state = default_conversation.copy()
84
- dropdown_update = gr.Dropdown(
85
- choices=models,
86
- value=models[0] if len(models) > 0 else ""
87
- )
88
- return state, dropdown_update
89
-
90
-
91
- def vote_last_response(state, vote_type, model_selector, request: gr.Request):
92
- with open(get_conv_log_filename(), "a") as fout:
93
- data = {
94
- "tstamp": round(time.time(), 4),
95
- "type": vote_type,
96
- "model": model_selector,
97
- "state": state.dict(),
98
- "ip": request.client.host,
99
- }
100
- fout.write(json.dumps(data) + "\n")
101
-
102
-
103
- def upvote_last_response(state, model_selector, request: gr.Request):
104
- logger.info(f"upvote. ip: {request.client.host}")
105
- vote_last_response(state, "upvote", model_selector, request)
106
- return ("",) + (disable_btn,) * 3
107
-
108
-
109
- def downvote_last_response(state, model_selector, request: gr.Request):
110
- logger.info(f"downvote. ip: {request.client.host}")
111
- vote_last_response(state, "downvote", model_selector, request)
112
- return ("",) + (disable_btn,) * 3
113
-
114
-
115
- def flag_last_response(state, model_selector, request: gr.Request):
116
- logger.info(f"flag. ip: {request.client.host}")
117
- vote_last_response(state, "flag", model_selector, request)
118
- return ("",) + (disable_btn,) * 3
119
-
120
-
121
- def regenerate(state, image_process_mode, request: gr.Request):
122
- logger.info(f"regenerate. ip: {request.client.host}")
123
- state.messages[-1][-1] = None
124
- prev_human_msg = state.messages[-2]
125
- if type(prev_human_msg[1]) in (tuple, list):
126
- prev_human_msg[1] = (*prev_human_msg[1][:2], image_process_mode)
127
- state.skip_next = False
128
- return (state, state.to_gradio_chatbot(), "", None) + (disable_btn,) * 5
129
-
130
-
131
- def clear_history(request: gr.Request):
132
- logger.info(f"clear_history. ip: {request.client.host}")
133
- state = default_conversation.copy()
134
- return (state, state.to_gradio_chatbot(), "", None) + (disable_btn,) * 5
135
-
136
-
137
- def add_text(state, text, image, image_process_mode, request: gr.Request):
138
- logger.info(f"add_text. ip: {request.client.host}. len: {len(text)}")
139
- if len(text) <= 0 or image is None:
140
- state.skip_next = True
141
- return (state, state.to_gradio_chatbot(), "", None) + (no_change_btn,) * 5
142
- if args.moderate:
143
- flagged = violates_moderation(text)
144
- if flagged:
145
- state.skip_next = True
146
- return (state, state.to_gradio_chatbot(), moderation_msg, None) + (
147
- no_change_btn,) * 5
148
-
149
- text = wrap_taxonomy(text)
150
- if image is not None:
151
- text = text # Hard cut-off for images
152
- if '<image>' not in text:
153
- # text = '<Image><image></Image>' + text
154
- text = text + '\n<image>'
155
- text = (text, image, image_process_mode)
156
- state = default_conversation.copy()
157
- state = clear_conv(state)
158
- state.append_message(state.roles[0], text)
159
- state.append_message(state.roles[1], None)
160
- state.skip_next = False
161
- return (state, state.to_gradio_chatbot(), default_taxonomy, None) + (disable_btn,) * 5
162
-
163
-
164
- def http_bot(state, model_selector, temperature, top_p, max_new_tokens, request: gr.Request):
165
- logger.info(f"http_bot. ip: {request.client.host}")
166
- start_tstamp = time.time()
167
- model_name = model_selector
168
-
169
- if state.skip_next:
170
- # This generate call is skipped due to invalid inputs
171
- yield (state, state.to_gradio_chatbot()) + (no_change_btn,) * 5
172
- return
173
-
174
- if len(state.messages) == state.offset + 2:
175
- # First round of conversation
176
- if "llava" in model_name.lower():
177
- if 'llama-2' in model_name.lower():
178
- template_name = "llava_llama_2"
179
- elif "mistral" in model_name.lower() or "mixtral" in model_name.lower():
180
- if 'orca' in model_name.lower():
181
- template_name = "mistral_orca"
182
- elif 'hermes' in model_name.lower():
183
- template_name = "chatml_direct"
184
- else:
185
- template_name = "mistral_instruct"
186
- elif 'llava-v1.6-34b' in model_name.lower():
187
- template_name = "chatml_direct"
188
- elif "v1" in model_name.lower():
189
- if 'mmtag' in model_name.lower():
190
- template_name = "v1_mmtag"
191
- elif 'plain' in model_name.lower() and 'finetune' not in model_name.lower():
192
- template_name = "v1_mmtag"
193
- else:
194
- template_name = "llava_v1"
195
- elif "mpt" in model_name.lower():
196
- template_name = "mpt"
197
- else:
198
- if 'mmtag' in model_name.lower():
199
- template_name = "v0_mmtag"
200
- elif 'plain' in model_name.lower() and 'finetune' not in model_name.lower():
201
- template_name = "v0_mmtag"
202
- else:
203
- template_name = "llava_v0"
204
- elif "mpt" in model_name:
205
- template_name = "mpt_text"
206
- elif "llama-2" in model_name:
207
- template_name = "llama_2"
208
- else:
209
- template_name = "vicuna_v1"
210
- new_state = conv_templates[template_name].copy()
211
- new_state.append_message(new_state.roles[0], state.messages[-2][1])
212
- new_state.append_message(new_state.roles[1], None)
213
- state = new_state
214
-
215
- # Query worker address
216
- controller_url = args.controller_url
217
- ret = requests.post(controller_url + "/get_worker_address",
218
- json={"model": model_name})
219
- worker_addr = ret.json()["address"]
220
- logger.info(f"model_name: {model_name}, worker_addr: {worker_addr}")
221
-
222
- # No available worker
223
- if worker_addr == "":
224
- state.messages[-1][-1] = server_error_msg
225
- yield (state, state.to_gradio_chatbot(), disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
226
- return
227
-
228
- # Construct prompt
229
- prompt = state.get_prompt()
230
-
231
- all_images = state.get_images(return_pil=True)
232
- all_image_hash = [hashlib.md5(image.tobytes()).hexdigest() for image in all_images]
233
- for image, hash in zip(all_images, all_image_hash):
234
- t = datetime.datetime.now()
235
- filename = os.path.join(LOGDIR, "serve_images", f"{t.year}-{t.month:02d}-{t.day:02d}", f"{hash}.jpg")
236
- if not os.path.isfile(filename):
237
- os.makedirs(os.path.dirname(filename), exist_ok=True)
238
- image.save(filename)
239
-
240
- # Make requests
241
- pload = {
242
- "model": model_name,
243
- "prompt": prompt,
244
- "temperature": float(temperature),
245
- "top_p": float(top_p),
246
- # "num_beams": 2,
247
- # "top_k": 50,
248
- "max_new_tokens": min(int(max_new_tokens), 1536),
249
- "stop": state.sep if state.sep_style in [SeparatorStyle.SINGLE, SeparatorStyle.MPT] else state.sep2,
250
- "images": f'List of {len(state.get_images())} images: {all_image_hash}',
251
- }
252
- logger.info(f"==== request ====\n{pload}")
253
-
254
- pload['images'] = state.get_images()
255
-
256
- state.messages[-1][-1] = "▌"
257
-
258
- yield (state, state.to_gradio_chatbot()) + (disable_btn,) * 5
259
-
260
- try:
261
- # Stream output
262
- response = requests.post(worker_addr + "/worker_generate_stream",
263
- headers=headers, json=pload, stream=True, timeout=10)
264
- for chunk in response.iter_lines(decode_unicode=False, delimiter=b"\0"):
265
- if chunk:
266
- data = json.loads(chunk.decode())
267
- if data["error_code"] == 0:
268
- output = data["text"][len(prompt):].strip()
269
- state.messages[-1][-1] = output + "▌"
270
- yield (state, state.to_gradio_chatbot()) + (disable_btn,) * 5
271
- else:
272
- output = data["text"] + f" (error_code: {data['error_code']})"
273
- state.messages[-1][-1] = output
274
- yield (state, state.to_gradio_chatbot()) + (
275
- disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
276
- return
277
- time.sleep(0.03)
278
- except requests.exceptions.RequestException as e:
279
- state.messages[-1][-1] = server_error_msg
280
- yield (state, state.to_gradio_chatbot()) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
281
- return
282
-
283
- state.messages[-1][-1] = state.messages[-1][-1][:-1]
284
- yield (state, state.to_gradio_chatbot()) + (enable_btn,) * 5
285
-
286
- finish_tstamp = time.time()
287
- logger.info(f"{output}")
288
-
289
- with open(get_conv_log_filename(), "a") as fout:
290
- data = {
291
- "tstamp": round(finish_tstamp, 4),
292
- "type": "chat",
293
- "model": model_name,
294
- "start": round(start_tstamp, 4),
295
- "finish": round(finish_tstamp, 4),
296
- "state": state.dict(),
297
- "images": all_image_hash,
298
- "ip": request.client.host,
299
- }
300
- fout.write(json.dumps(data) + "\n")
301
-
302
-
303
- title_markdown = ("""
304
- # LLAVAGUARD: VLM-based Safeguard for Vision Dataset Curation and Safety Assessment
305
- [[Project Page](https://ml-research.github.io/human-centered-genai/projects/llavaguard/index.html)]
306
- [[Code](https://github.com/ml-research/LlavaGuard)]
307
- [[Model](https://huggingface.co/collections/AIML-TUDA/llavaguard-665b42e89803408ee8ec1086)]
308
- [[Dataset](https://huggingface.co/datasets/aiml-tuda/llavaguard)]
309
- [[LavaGuard](https://arxiv.org/abs/2406.05113)]
310
- """)
311
-
312
- tos_markdown = ("""
313
- ### Terms of use
314
- By using this service, users are required to agree to the following terms:
315
- The service is a research preview intended for non-commercial use only. It only provides limited safety measures and may generate offensive content. It must not be used for any illegal, harmful, violent, racist, or sexual purposes. The service may collect user dialogue data for future research.
316
- Please click the "Flag" button if you get any inappropriate answer! We will collect those to keep improving our moderator.
317
- For an optimal experience, please use desktop computers for this demo, as mobile devices may compromise its quality.
318
- """)
319
-
320
- learn_more_markdown = ("""
321
- ### License
322
- The service is a research preview intended for non-commercial use only, subject to the model [License](https://github.com/facebookresearch/llama/blob/main/MODEL_CARD.md) of LLaMA, [Terms of Use](https://openai.com/policies/terms-of-use) of the data generated by OpenAI, and [Privacy Practices](https://chrome.google.com/webstore/detail/sharegpt-share-your-chatg/daiacboceoaocpibfodeljbdfacokfjb) of ShareGPT. Please contact us if you find any potential violation.
323
- """)
324
-
325
- block_css = """
326
-
327
- #buttons button {
328
- min-width: min(120px,100%);
329
- }
330
-
331
- """
332
-
333
- taxonomies = ["Default", "Modified w/ O1 non-violating", "Default message 3"]
334
-
335
-
336
- def build_demo(embed_mode, cur_dir=None, concurrency_count=10):
337
- with gr.Accordion("Safety Risk Taxonomy", open=False) as accordion:
338
- textbox = gr.Textbox(
339
- label="Safety Risk Taxonomy",
340
- show_label=True,
341
- placeholder="Enter your safety policy here",
342
- container=True,
343
- value=default_taxonomy,
344
- lines=50)
345
- with gr.Blocks(title="LlavaGuard", theme=gr.themes.Default(), css=block_css) as demo:
346
- state = gr.State()
347
-
348
- if not embed_mode:
349
- gr.Markdown(title_markdown)
350
-
351
- with gr.Row():
352
- with gr.Column(scale=3):
353
- with gr.Row(elem_id="model_selector_row"):
354
- model_selector = gr.Dropdown(
355
- choices=models,
356
- value=models[0] if len(models) > 0 else "",
357
- interactive=True,
358
- show_label=False,
359
- container=False)
360
-
361
- imagebox = gr.Image(type="pil", label="Image", container=False)
362
- image_process_mode = gr.Radio(
363
- ["Crop", "Resize", "Pad", "Default"],
364
- value="Default",
365
- label="Preprocess for non-square image", visible=False)
366
-
367
- if cur_dir is None:
368
- cur_dir = os.path.dirname(os.path.abspath(__file__))
369
- gr.Examples(examples=[
370
- [f"{cur_dir}/examples/image{i}.png"] for i in range(1,6)
371
- ], inputs=imagebox)
372
-
373
- with gr.Accordion("Parameters", open=False) as parameter_row:
374
- temperature = gr.Slider(minimum=0.0, maximum=1.0, value=0.2, step=0.1, interactive=True,
375
- label="Temperature", )
376
- top_p = gr.Slider(minimum=0.0, maximum=1.0, value=0.95, step=0.1, interactive=True, label="Top P", )
377
- max_output_tokens = gr.Slider(minimum=0, maximum=1024, value=512, step=64, interactive=True,
378
- label="Max output tokens", )
379
-
380
- with gr.Column(scale=8):
381
- chatbot = gr.Chatbot(
382
- elem_id="chatbot",
383
- label="LLavaGuard Safety Assessment",
384
- height=650,
385
- layout="panel",
386
- )
387
- with gr.Row():
388
- with gr.Column(scale=8):
389
- textbox.render()
390
- with gr.Column(scale=1, min_width=50):
391
- submit_btn = gr.Button(value="Send", variant="primary")
392
- with gr.Row(elem_id="buttons") as button_row:
393
- upvote_btn = gr.Button(value="👍 Upvote", interactive=False)
394
- downvote_btn = gr.Button(value="👎 Downvote", interactive=False)
395
- flag_btn = gr.Button(value="⚠️ Flag", interactive=False)
396
- # stop_btn = gr.Button(value="⏹️ Stop Generation", interactive=False)
397
- regenerate_btn = gr.Button(value="🔄 Regenerate", interactive=False)
398
- clear_btn = gr.Button(value="🗑️ Clear", interactive=False)
399
-
400
- if not embed_mode:
401
- gr.Markdown(tos_markdown)
402
- gr.Markdown(learn_more_markdown)
403
- url_params = gr.JSON(visible=False)
404
-
405
- # Register listeners
406
- btn_list = [upvote_btn, downvote_btn, flag_btn, regenerate_btn, clear_btn]
407
- upvote_btn.click(
408
- upvote_last_response,
409
- [state, model_selector],
410
- [textbox, upvote_btn, downvote_btn, flag_btn]
411
- )
412
- downvote_btn.click(
413
- downvote_last_response,
414
- [state, model_selector],
415
- [textbox, upvote_btn, downvote_btn, flag_btn]
416
- )
417
- flag_btn.click(
418
- flag_last_response,
419
- [state, model_selector],
420
- [textbox, upvote_btn, downvote_btn, flag_btn]
421
- )
422
-
423
- regenerate_btn.click(
424
- regenerate,
425
- [state, image_process_mode],
426
- [state, chatbot, textbox, imagebox] + btn_list
427
- ).then(
428
- http_bot,
429
- [state, model_selector, temperature, top_p, max_output_tokens],
430
- [state, chatbot] + btn_list,
431
- concurrency_limit=concurrency_count
432
- )
433
-
434
- clear_btn.click(
435
- clear_history,
436
- None,
437
- [state, chatbot, textbox, imagebox] + btn_list,
438
- queue=False
439
- )
440
-
441
- textbox.submit(
442
- add_text,
443
- [state, textbox, imagebox, image_process_mode],
444
- [state, chatbot, textbox, imagebox] + btn_list,
445
- queue=False
446
- ).then(
447
- http_bot,
448
- [state, model_selector, temperature, top_p, max_output_tokens],
449
- [state, chatbot] + btn_list,
450
- concurrency_limit=concurrency_count
451
- )
452
-
453
- submit_btn.click(
454
- add_text,
455
- [state, textbox, imagebox, image_process_mode],
456
- [state, chatbot, textbox, imagebox] + btn_list
457
- ).then(
458
- http_bot,
459
- [state, model_selector, temperature, top_p, max_output_tokens],
460
- [state, chatbot] + btn_list,
461
- concurrency_limit=concurrency_count
462
- )
463
-
464
- if args.model_list_mode == "once":
465
- demo.load(
466
- load_demo,
467
- [url_params],
468
- [state, model_selector],
469
- js=get_window_url_params
470
- )
471
- elif args.model_list_mode == "reload":
472
- demo.load(
473
- load_demo_refresh_model_list,
474
- None,
475
- [state, model_selector],
476
- queue=False
477
- )
478
- else:
479
- raise ValueError(f"Unknown model list mode: {args.model_list_mode}")
480
-
481
- return demo
482
-
483
-
484
- if __name__ == "__main__":
485
- parser = argparse.ArgumentParser()
486
- parser.add_argument("--host", type=str, default="0.0.0.0")
487
- parser.add_argument("--port", type=int)
488
- parser.add_argument("--controller-url", type=str, default="http://localhost:21001")
489
- parser.add_argument("--concurrency-count", type=int, default=16)
490
- parser.add_argument("--model-list-mode", type=str, default="once",
491
- choices=["once", "reload"])
492
- parser.add_argument("--share", action="store_true")
493
- parser.add_argument("--moderate", action="store_true")
494
- parser.add_argument("--embed", action="store_true")
495
- args = parser.parse_args()
496
- logger.info(f"args: {args}")
497
-
498
- models = get_model_list()
499
-
500
- logger.info(args)
501
- demo = build_demo(args.embed, concurrency_count=args.concurrency_count)
502
- demo.queue(
503
- api_open=False
504
- ).launch(
505
- server_name=args.host,
506
- server_port=args.port,
507
- share=args.share
508
- )