Pisces / app.py
jiuhai's picture
long-caption
d31ac22
raw
history blame
20.7 kB
# import gradio as gr
# import os
# import torch
# import spaces
# from llava import conversation as conversation_lib
# from llava.constants import IMAGE_TOKEN_IDX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
# from llava.conversation import conv_templates, SeparatorStyle
# from llava.model.builder import load_pretrained_model
# from llava.utils import disable_torch_init
# from llava.mm_utils import tokenizer_image_token, get_model_name_from_path, process_images
# from PIL import Image
# import argparse
# from transformers import TextIteratorStreamer
# from threading import Thread
# import subprocess
# # Install flash attention, skipping CUDA build if necessary
# subprocess.run(
# "pip install flash-attn --no-build-isolation",
# env={"FLASH_ATTENTION_SKIP_CUDA_BUILD": "TRUE"},
# shell=True,
# )
# # os.environ['GRADIO_TEMP_DIR'] = './gradio_tmp'
# no_change_btn = gr.Button()
# enable_btn = gr.Button(interactive=True)
# disable_btn = gr.Button(interactive=False)
# argparser = argparse.ArgumentParser()
# argparser.add_argument("--model-path", default="umd-vt-nyu/clip-evaclip-und-gen-sft", type=str)
# argparser.add_argument("--model-base", type=str, default=None)
# argparser.add_argument("--num-gpus", type=int, default=1)
# argparser.add_argument("--conv-mode", type=str, default="llama3")
# argparser.add_argument("--temperature", type=float, default=0.2)
# argparser.add_argument("--max-new-tokens", type=int, default=64)
# argparser.add_argument("--num_frames", type=int, default=16)
# argparser.add_argument("--load-8bit", action="store_true")
# argparser.add_argument("--load-4bit", action="store_true")
# argparser.add_argument("--debug", action="store_true")
# args = argparser.parse_args()
# model_path = args.model_path
# conv_mode = args.conv_mode
# filt_invalid="cut"
# model_name = get_model_name_from_path(args.model_path)
# model_name = 'clip-evaclip-und-gen-sft'
# model_kwargs = {
# "use_cache": False,
# "trust_remote_code": True,
# "torch_dtype": torch.bfloat16,
# "attn_implementation": "sdpa"
# }
# tokenizer, model, image_processor, context_len = load_pretrained_model(args.model_path, args.model_base, model_name, device_map="cuda:0", **model_kwargs)
# our_chatbot = None
# def upvote_last_response(state):
# return ("",) + (disable_btn,) * 3
# def downvote_last_response(state):
# return ("",) + (disable_btn,) * 3
# def flag_last_response(state):
# return ("",) + (disable_btn,) * 3
# def clear_history():
# state =conv_templates[conv_mode].copy()
# return (state, state.to_gradio_chatbot(), "", None) + (disable_btn,) * 5
# def add_text(state, imagebox, textbox, image_process_mode):
# if state is None:
# state = conv_templates[conv_mode].copy()
# if imagebox is not None:
# textbox = DEFAULT_IMAGE_TOKEN + '\n' + textbox
# image = Image.open(imagebox).convert('RGB')
# if imagebox is not None:
# textbox = (textbox, image, image_process_mode)
# state.append_message(state.roles[0], textbox)
# state.append_message(state.roles[1], None)
# yield (state, state.to_gradio_chatbot(), "", None) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
# def delete_text(state, image_process_mode):
# state.messages[-1][-1] = None
# prev_human_msg = state.messages[-2]
# if type(prev_human_msg[1]) in (tuple, list):
# prev_human_msg[1] = (*prev_human_msg[1][:2], image_process_mode)
# yield (state, state.to_gradio_chatbot(), "", None) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
# def regenerate(state, image_process_mode):
# state.messages[-1][-1] = None
# prev_human_msg = state.messages[-2]
# if type(prev_human_msg[1]) in (tuple, list):
# prev_human_msg[1] = (*prev_human_msg[1][:2], image_process_mode)
# state.skip_next = False
# return (state, state.to_gradio_chatbot(), "", None) + (disable_btn,) * 5
# @spaces.GPU
# def generate(state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens):
# prompt = state.get_prompt()
# images = state.get_images(return_pil=True)
# #prompt, image_args = process_image(prompt, images)
# ori_prompt = prompt
# num_image_tokens = 0
# if images is not None and len(images) > 0:
# if len(images) > 0:
# if len(images) != prompt.count(DEFAULT_IMAGE_TOKEN):
# raise ValueError("Number of images does not match number of <image> tokens in prompt")
# #images = [load_image_from_base64(image) for image in images]
# image_sizes = [image.size for image in images]
# images = process_images(images, image_processor, model.config)
# if type(images) is list:
# images = [image.to(model.device, dtype=torch.float16) for image in images]
# else:
# images = images.to(model.device, dtype=torch.float16)
# else:
# images = None
# image_sizes = None
# image_args = {"images": images, "image_sizes": image_sizes}
# else:
# images = None
# image_args = {}
# max_context_length = getattr(model.config, 'max_position_embeddings', 2048)
# max_new_tokens = 512
# do_sample = True if temperature > 0.001 else False
# stop_str = state.sep if state.sep_style in [SeparatorStyle.SINGLE, SeparatorStyle.MPT] else state.sep2
# input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_IDX, return_tensors='pt').unsqueeze(0).to(model.device)
# streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=15)
# max_new_tokens = min(max_new_tokens, max_context_length - input_ids.shape[-1] - num_image_tokens)
# if max_new_tokens < 1:
# # yield json.dumps({"text": ori_prompt + "Exceeds max token length. Please start a new conversation, thanks.", "error_code": 0}).encode() + b"\0"
# return
# thread = Thread(target=model.generate, kwargs=dict(
# inputs=input_ids,
# do_sample=do_sample,
# temperature=temperature,
# top_p=top_p,
# max_new_tokens=max_new_tokens,
# streamer=streamer,
# use_cache=True,
# pad_token_id=tokenizer.eos_token_id,
# **image_args
# ))
# thread.start()
# generated_text = ''
# for new_text in streamer:
# generated_text += new_text
# if generated_text.endswith(stop_str):
# generated_text = generated_text[:-len(stop_str)]
# state.messages[-1][-1] = generated_text
# yield (state, state.to_gradio_chatbot(), "", None) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
# yield (state, state.to_gradio_chatbot(), "", None) + (enable_btn,) * 5
# torch.cuda.empty_cache()
# txt = gr.Textbox(
# scale=4,
# show_label=False,
# placeholder="Enter text and press enter.",
# container=False,
# )
# title_markdown = ("""
# # Florence-llama
# [[Code](TBD)] [[Model](TBD)] | 📚 [[Arxiv](TBD)]]
# """)
# # title_markdown = ("""
# # # Florence-llama
# # """)
# tos_markdown = ("""
# ### Terms of use
# By using this service, users are required to agree to the following terms:
# 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.
# Please click the "Flag" button if you get any inappropriate answer! We will collect those to keep improving our moderator.
# For an optimal experience, please use desktop computers for this demo, as mobile devices may compromise its quality.
# """)
# learn_more_markdown = ("""
# ### License
# The service is a research preview intended for non-commercial use only, subject to the. Please contact us if you find any potential violation.
# """)
# block_css = """
# #buttons button {
# min-width: min(120px,100%);
# }
# """
# textbox = gr.Textbox(show_label=False, placeholder="Enter text and press ENTER", container=False)
# with gr.Blocks(title="llava", theme=gr.themes.Default(), css=block_css) as demo:
# state = gr.State()
# gr.Markdown(title_markdown)
# with gr.Row():
# with gr.Column(scale=3):
# imagebox = gr.Image(label="Input Image", type="filepath")
# image_process_mode = gr.Radio(
# ["Crop", "Resize", "Pad", "Default"],
# value="Default",
# label="Preprocess for non-square image", visible=False)
# cur_dir = os.path.dirname(os.path.abspath(__file__))
# # gr.Examples(examples=[
# # [f"{cur_dir}/assets/health-insurance.png", "Under which circumstances do I need to be enrolled in mandatory health insurance if I am an international student?"],
# # [f"{cur_dir}/assets/leasing-apartment.png", "I don't have any 3rd party renter's insurance now. Do I need to get one for myself?"],
# # [f"{cur_dir}/assets/nvidia.jpeg", "Who is the person in the middle?"],
# # [f"{cur_dir}/assets/animal-compare.png", "Are these two pictures showing the same kind of animal?"],
# # [f"{cur_dir}/assets/georgia-tech.jpeg", "Where is this photo taken?"]
# # ], inputs=[imagebox, textbox], cache_examples=False)
# gr.Examples(examples=[
# [f"{cur_dir}/assets/animal-compare.png", "Provide a detailed description of the given image."]
# ], inputs=[imagebox, textbox], cache_examples=False)
# with gr.Accordion("Parameters", open=False) as parameter_row:
# temperature = gr.Slider(minimum=0.0, maximum=1.0, value=0.2, step=0.1, interactive=True, label="Temperature",)
# top_p = gr.Slider(minimum=0.0, maximum=1.0, value=0.7, step=0.1, interactive=True, label="Top P",)
# max_output_tokens = gr.Slider(minimum=0, maximum=1024, value=512, step=64, interactive=True, label="Max output tokens",)
# with gr.Column(scale=8):
# chatbot = gr.Chatbot(
# elem_id="chatbot",
# label="llava Chatbot",
# height=650,
# layout="panel",
# )
# with gr.Row():
# with gr.Column(scale=8):
# textbox.render()
# with gr.Column(scale=1, min_width=50):
# submit_btn = gr.Button(value="Send", variant="primary")
# with gr.Row(elem_id="buttons") as button_row:
# upvote_btn = gr.Button(value="👍 Upvote", interactive=False)
# downvote_btn = gr.Button(value="👎 Downvote", interactive=False)
# flag_btn = gr.Button(value="⚠️ Flag", interactive=False)
# stop_btn = gr.Button(value="⏹️ Stop Generation", interactive=False)
# regenerate_btn = gr.Button(value="🔄 Regenerate", interactive=False)
# clear_btn = gr.Button(value="🗑️ Clear", interactive=False)
# gr.Markdown(tos_markdown)
# gr.Markdown(learn_more_markdown)
# url_params = gr.JSON(visible=False)
# # Register listeners
# btn_list = [upvote_btn, downvote_btn, flag_btn, regenerate_btn, clear_btn]
# upvote_btn.click(
# upvote_last_response,
# [state],
# [textbox, upvote_btn, downvote_btn, flag_btn]
# )
# downvote_btn.click(
# downvote_last_response,
# [state],
# [textbox, upvote_btn, downvote_btn, flag_btn]
# )
# flag_btn.click(
# flag_last_response,
# [state],
# [textbox, upvote_btn, downvote_btn, flag_btn]
# )
# clear_btn.click(
# clear_history,
# None,
# [state, chatbot, textbox, imagebox] + btn_list,
# queue=False
# )
# regenerate_btn.click(
# delete_text,
# [state, image_process_mode],
# [state, chatbot, textbox, imagebox] + btn_list,
# ).then(
# generate,
# [state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens],
# [state, chatbot, textbox, imagebox] + btn_list,
# )
# textbox.submit(
# add_text,
# [state, imagebox, textbox, image_process_mode],
# [state, chatbot, textbox, imagebox] + btn_list,
# ).then(
# generate,
# [state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens],
# [state, chatbot, textbox, imagebox] + btn_list,
# )
# submit_btn.click(
# add_text,
# [state, imagebox, textbox, image_process_mode],
# [state, chatbot, textbox, imagebox] + btn_list,
# ).then(
# generate,
# [state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens],
# [state, chatbot, textbox, imagebox] + btn_list,
# )
# demo.queue(
# status_update_rate=10,
# api_open=False
# ).launch()
import gradio as gr
import os
import torch
import argparse
from transformers import TextIteratorStreamer
from threading import Thread
from PIL import Image
from llava import conversation as conversation_lib
from llava.constants import *
from llava.conversation import conv_templates, SeparatorStyle
from llava.model.builder import load_pretrained_model
from llava.utils import disable_torch_init
from llava.mm_utils import tokenizer_image_token, get_model_name_from_path, process_images
from diffusers import DiffusionPipeline
# Define paths and configurations
# diffusion_path = "/export/jchen169/hub/models--BAAI--Emu2-Gen/snapshots/a41a2dcd777a68225dddc72c7213b064ee06f4a0"
argparser = argparse.ArgumentParser()
argparser.add_argument("--model-path", default="umd-vt-nyu/clip-evaclip-und-gen-pretrain-long-caption", type=str)
argparser.add_argument("--conv-mode", type=str, default="llama3")
argparser.add_argument("--temperature", type=float, default=0.2)
argparser.add_argument("--max-new-tokens", type=int, default=64)
argparser.add_argument("--num_frames", type=int, default=16)
argparser.add_argument("--load-8bit", action="store_true")
argparser.add_argument("--load-4bit", action="store_true")
argparser.add_argument("--debug", action="store_true")
args = argparser.parse_args()
# Load LLaVA model
disable_torch_init()
model_name = get_model_name_from_path(args.model_path)
tokenizer, model, image_processor, context_len = load_pretrained_model(args.model_path, None, model_name)
our_chatbot = None
# Load Diffusion model for image generation
pipe = DiffusionPipeline.from_pretrained(
'BAAI/Emu2-Gen',
custom_pipeline="pipeline_llava_gen",
torch_dtype=torch.bfloat16,
use_safetensors=True,
variant="bf16",
multimodal_encoder=model,
tokenizer=tokenizer,
)
pipe.vae.to("cuda:0")
pipe.unet.to("cuda:0")
pipe.safety_checker.to("cuda:0")
def upvote_last_response(state):
return ("",) + (disable_btn,) * 3
def downvote_last_response(state):
return ("",) + (disable_btn,) * 3
def flag_last_response(state):
return ("",) + (disable_btn,) * 3
def clear_history():
state = conv_templates[conv_mode].copy()
return (state, state.to_gradio_chatbot(), "", None) + (disable_btn,) * 5
def add_text(state, imagebox, textbox, image_process_mode):
if state is None:
state = conv_templates[conv_mode].copy()
if imagebox is not None:
textbox = DEFAULT_IMAGE_TOKEN + '\n' + textbox
image = Image.open(imagebox).convert('RGB')
if imagebox is not None:
textbox = (textbox, image, image_process_mode)
state.append_message(state.roles[0], textbox)
state.append_message(state.roles[1], None)
yield (state, state.to_gradio_chatbot(), "", None) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
def generate(state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens):
prompt = state.get_prompt()
images = state.get_images(return_pil=True)
ori_prompt = prompt
num_image_tokens = 0
if images is not None and len(images) > 0:
if len(images) > 0:
if len(images) != prompt.count(DEFAULT_IMAGE_TOKEN):
raise ValueError("Number of images does not match number of <image> tokens in prompt")
image_sizes = [image.size for image in images]
images = process_images(images, image_processor, model.config)
if type(images) is list:
images = [image.to(model.device, dtype=torch.float16) for image in images]
else:
images = images.to(model.device, dtype=torch.float16)
else:
images = None
image_sizes = None
image_args = {"images": images, "image_sizes": image_sizes}
else:
images = None
image_args = {}
max_context_length = getattr(model.config, 'max_position_embeddings', 2048)
max_new_tokens = 512
do_sample = True if temperature > 0.001 else False
stop_str = state.sep if state.sep_style in [SeparatorStyle.SINGLE, SeparatorStyle.MPT] else state.sep2
input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_IDX, return_tensors='pt').unsqueeze(0).to(model.device)
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=15)
max_new_tokens = min(max_new_tokens, max_context_length - input_ids.shape[-1] - num_image_tokens)
if max_new_tokens < 1:
return
thread = Thread(target=model.generate, kwargs=dict(
inputs=input_ids,
do_sample=do_sample,
temperature=temperature,
top_p=top_p,
max_new_tokens=max_new_tokens,
streamer=streamer,
use_cache=True,
pad_token_id=tokenizer.eos_token_id,
**image_args
))
thread.start()
generated_text = ''
for new_text in streamer:
generated_text += new_text
if generated_text.endswith(stop_str):
generated_text = generated_text[:-len(stop_str)]
state.messages[-1][-1] = generated_text
yield (state, state.to_gradio_chatbot(), "", None) + (disable_btn, disable_btn, disable_btn, enable_btn, enable_btn)
yield (state, state.to_gradio_chatbot(), "", None) + (enable_btn,) * 5
torch.cuda.empty_cache()
def add_template(prompt):
conv = conv_templates['llama3'].copy()
conv.append_message(conv.roles[0], prompt[0])
conv.append_message(conv.roles[1], None)
prompt = conv.get_prompt()
return [prompt]
def generate_image(prompt):
prompt = add_template(prompt)
gen_img = pipe(prompt, guidance_scale=3.0)
return gen_img.image
# Interface setup
with gr.Blocks(title="LLaVA Chatbot with Image Generation") as demo:
state = gr.State()
gr.Markdown("# LLaVA Chatbot with Image Generation")
with gr.Row():
with gr.Column(scale=3):
imagebox = gr.Image(label="Input Image", type="filepath")
image_process_mode = gr.Radio(
["Crop", "Resize", "Pad", "Default"],
value="Default",
label="Preprocess for non-square image", visible=False)
temperature = gr.Slider(minimum=0.0, maximum=1.0, value=0.2, step=0.1, interactive=True, label="Temperature")
top_p = gr.Slider(minimum=0.0, maximum=1.0, value=0.7, step=0.1, interactive=True, label="Top P")
max_output_tokens = gr.Slider(minimum=0, maximum=1024, value=512, step=64, interactive=True, label="Max output tokens")
with gr.Column(scale=8):
chatbot = gr.Chatbot(label="LLaVA Chatbot", height=650, layout="panel")
textbox = gr.Textbox(show_label=False, placeholder="Enter text and press ENTER", container=False)
submit_btn = gr.Button(value="Send", variant="primary")
with gr.Row() as button_row:
clear_btn = gr.Button(value="🗑️ Clear", interactive=False)
# Define actions
submit_btn.click(
lambda state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens: (
generate_image([textbox]) if "generate image" in textbox.lower() else add_text(
state, imagebox, textbox, image_process_mode)),
[state, imagebox, textbox, image_process_mode, temperature, top_p, max_output_tokens],
[state, chatbot, textbox, imagebox]
)
demo.queue(status_update_rate=10, api_open=False).launch()