CoolFace
Apppublic

OpenGVLab/InternVL

sourceHugging Facemitupdated 2y agoView on Hugging Face
510likes
app.py662 linesDownload Raw Back to root
1import spaces2import argparse3from ast import parse4import datetime5import json6import os7import time8import hashlib9import re10 11import gradio as gr12import requests13import random14from filelock import FileLock15from io import BytesIO16from PIL import Image, ImageDraw, ImageFont17 18from constants import LOGDIR19from utils import (20    build_logger,21    server_error_msg,22    violates_moderation,23    moderation_msg,24    load_image_from_base64,25    get_log_filename,26)27from conversation import Conversation28 29logger = build_logger("gradio_web_server", "gradio_web_server.log")30 31headers = {"User-Agent": "InternVL-Chat Client"}32 33no_change_btn = gr.Button()34enable_btn = gr.Button(interactive=True)35disable_btn = gr.Button(interactive=False)36 37 38@spaces.GPU(duration=10)39def make_zerogpu_happy():40    pass41 42 43def write2file(path, content):44    lock = FileLock(f"{path}.lock")45    with lock:46        with open(path, "a") as fout:47            fout.write(content)48 49 50get_window_url_params = """51function() {52    const params = new URLSearchParams(window.location.search);53    url_params = Object.fromEntries(params);54    console.log(url_params);55    return url_params;56    }57"""58 59 60def init_state(state=None):61    if state is not None:62        del state63    return Conversation()64 65 66def find_bounding_boxes(state, response):67    pattern = re.compile(r"<ref>\s*(.*?)\s*</ref>\s*<box>\s*(\[\[.*?\]\])\s*</box>")68    matches = pattern.findall(response)69    results = []70    for match in matches:71        results.append((match[0], eval(match[1])))72    returned_image = None73    latest_image = state.get_images(source=state.USER)[-1]74    returned_image = latest_image.copy()75    width, height = returned_image.size76    draw = ImageDraw.Draw(returned_image)77    for result in results:78        line_width = max(1, int(min(width, height) / 200))79        random_color = (80            random.randint(0, 128),81            random.randint(0, 128),82            random.randint(0, 128),83        )84        category_name, coordinates = result85        coordinates = [86            (87                float(x[0]) / 1000,88                float(x[1]) / 1000,89                float(x[2]) / 1000,90                float(x[3]) / 1000,91            )92            for x in coordinates93        ]94        coordinates = [95            (96                int(x[0] * width),97                int(x[1] * height),98                int(x[2] * width),99                int(x[3] * height),100            )101            for x in coordinates102        ]103        for box in coordinates:104            draw.rectangle(box, outline=random_color, width=line_width)105            font = ImageFont.truetype("assets/SimHei.ttf", int(20 * line_width / 2))106            text_size = font.getbbox(category_name)107            text_width, text_height = (108                text_size[2] - text_size[0],109                text_size[3] - text_size[1],110            )111            text_position = (box[0], max(0, box[1] - text_height))112            draw.rectangle(113                [114                    text_position,115                    (text_position[0] + text_width, text_position[1] + text_height),116                ],117                fill=random_color,118            )119            draw.text(text_position, category_name, fill="white", font=font)120    return returned_image if len(matches) > 0 else None121 122 123def vote_last_response(state, liked, request: gr.Request):124    conv_data = {125        "tstamp": round(time.time(), 4),126        "like": liked,127        "model": 'InternVL2.5-78B',128        "state": state.dict(),129        "ip": request.client.host,130    }131    write2file(get_log_filename(), json.dumps(conv_data) + "\n")132 133 134def upvote_last_response(state, request: gr.Request):135    logger.info(f"upvote. ip: {request.client.host}")136    vote_last_response(state, True, request)137    textbox = gr.MultimodalTextbox(value=None, interactive=True)138    return (textbox,) + (disable_btn,) * 3139 140 141def downvote_last_response(state, request: gr.Request):142    logger.info(f"downvote. ip: {request.client.host}")143    vote_last_response(state, False, request)144    textbox = gr.MultimodalTextbox(value=None, interactive=True)145    return (textbox,) + (disable_btn,) * 3146 147 148def vote_selected_response(149    state, request: gr.Request, data: gr.LikeData150):151    logger.info(152        f"Vote: {data.liked}, index: {data.index}, value: {data.value} , ip: {request.client.host}"153    )154    conv_data = {155        "tstamp": round(time.time(), 4),156        "like": data.liked,157        "index": data.index,158        "model": 'InternVL2.5-78B',159        "state": state.dict(),160        "ip": request.client.host,161    }162    write2file(get_log_filename(), json.dumps(conv_data) + "\n")163    return164 165 166def flag_last_response(state, request: gr.Request):167    logger.info(f"flag. ip: {request.client.host}")168    vote_last_response(state, "flag", request)169    textbox = gr.MultimodalTextbox(value=None, interactive=True)170    return (textbox,) + (disable_btn,) * 3171 172 173def regenerate(state, image_process_mode, request: gr.Request):174    logger.info(f"regenerate. ip: {request.client.host}")175    # state.messages[-1][-1] = None176    state.update_message(Conversation.ASSISTANT, content='', image=None, idx=-1)177    prev_human_msg = state.messages[-2]178    if type(prev_human_msg[1]) in (tuple, list):179        prev_human_msg[1] = (*prev_human_msg[1][:2], image_process_mode)180    state.skip_next = False181    textbox = gr.MultimodalTextbox(value=None, interactive=True)182    return (state, state.to_gradio_chatbot(), textbox) + (disable_btn,) * 5183 184 185def clear_history(request: gr.Request):186    logger.info(f"clear_history. ip: {request.client.host}")187    state = init_state()188    textbox = gr.MultimodalTextbox(value=None, interactive=True)189    return (state, state.to_gradio_chatbot(), textbox) + (disable_btn,) * 5190 191 192def add_text(state, message, system_prompt, request: gr.Request):193    print(f"state: {state}")194    if not state:195        state = init_state()196    images = message.get("files", [])197    text = message.get("text", "").strip()198    logger.info(f"add_text. ip: {request.client.host}. len: {len(text)}")199    # import pdb; pdb.set_trace()200    textbox = gr.MultimodalTextbox(value=None, interactive=False)201    if len(text) <= 0 and len(images) == 0:202        state.skip_next = True203        return (state, state.to_gradio_chatbot(), textbox) + (no_change_btn,) * 5204    if args.moderate:205        flagged = violates_moderation(text)206        if flagged:207            state.skip_next = True208            textbox = gr.MultimodalTextbox(209                value={"text": moderation_msg}, interactive=True210            )211            return (state, state.to_gradio_chatbot(), textbox) + (no_change_btn,) * 5212    images = [Image.open(path).convert("RGB") for path in images]213 214    if len(images) > 0 and len(state.get_images(source=state.USER)) > 0:215        state = init_state(state)216    state.set_system_message(system_prompt)217    state.append_message(Conversation.USER, text, images)218    state.skip_next = False219    return (state, state.to_gradio_chatbot(), textbox) + (220        disable_btn,221    ) * 5222 223 224def http_bot(225    state,226    temperature,227    top_p,228    repetition_penalty,229    max_new_tokens,230    max_input_tiles,231    request: gr.Request,232):233    model_name = 'InternVL2.5-78B'234    logger.info(f"http_bot. ip: {request.client.host}")235    start_tstamp = time.time()236    if hasattr(state, "skip_next") and state.skip_next:237        # This generate call is skipped due to invalid inputs238        yield (239            state,240            state.to_gradio_chatbot(),241            gr.MultimodalTextbox(interactive=False),242        ) + (no_change_btn,) * 5243        return244 245    worker_addr = os.environ.get("WORKER_ADDR", "")246    api_token = os.environ.get("API_TOKEN", "")247    # headers = {"Authorization": f"{api_token}", "Content-Type": "application/json"}248    headers = {249        "Authorization": f"Bearer {api_token}", 250        "Content-Type": "application/json", 251        "Cookie": "acw_tc=65efca1a-119e-4da4-8fd6-338f5b70f29afaa1be67470ba113e38318b0208a00b2"252    }253 254    # No available worker255    if worker_addr == "":256        # state.messages[-1][-1] = server_error_msg257        state.update_message(Conversation.ASSISTANT, server_error_msg)258        yield (259            state,260            state.to_gradio_chatbot(),261            gr.MultimodalTextbox(interactive=False),262            disable_btn,263            disable_btn,264            disable_btn,265            enable_btn,266            enable_btn,267        )268        return269 270    all_images = state.get_images(source=state.USER)271    all_image_paths = [state.save_image(image) for image in all_images]272 273    # Make requests274    pload = {275        "model": model_name,276        "messages": state.get_prompt_v2(inlude_image=True, max_dynamic_patch=max_input_tiles),277        "temperature": float(temperature),278        "top_p": float(top_p),279        "max_tokens": max_new_tokens,280        "repetition_penalty": repetition_penalty,281        "stream": True282    }283    logger.info(f"==== request ====\n{pload}")284    state.append_message(Conversation.ASSISTANT, state.streaming_placeholder)285    yield (286        state,287        state.to_gradio_chatbot(),288        gr.MultimodalTextbox(interactive=False),289    ) + (disable_btn,) * 5290 291    try:292        # Stream output293        response = requests.post(worker_addr, json=pload, headers=headers, stream=True, timeout=300)294        finnal_output = ''295        for chunk in response.iter_lines(decode_unicode=False, delimiter=b"\n"):296            if chunk:297                chunk = chunk.decode()298                if chunk == 'data: [DONE]':299                    break300                if chunk.startswith("data:"):301                    chunk = chunk[5:]302                    chunk = json.loads(chunk)303                    output = chunk['choices'][0]['delta']['content']304                    finnal_output += output305                306                state.update_message(Conversation.ASSISTANT, finnal_output + state.streaming_placeholder, None)307                yield (308                    state,309                    state.to_gradio_chatbot(),310                    gr.MultimodalTextbox(interactive=False),311                ) + (disable_btn,) * 5312    except requests.exceptions.RequestException as e:313        state.update_message(Conversation.ASSISTANT, server_error_msg, None)314        yield (315            state,316            state.to_gradio_chatbot(),317            gr.MultimodalTextbox(interactive=True),318        ) + (319            disable_btn,320            disable_btn,321            disable_btn,322            enable_btn,323            enable_btn,324        )325        return326 327    ai_response = state.return_last_message()328    if "<ref>" in ai_response:329        returned_image = find_bounding_boxes(state, ai_response)330        returned_image = [returned_image] if returned_image else []331        state.update_message(Conversation.ASSISTANT, ai_response, returned_image)332 333    state.end_of_current_turn()334 335    yield (336        state,337        state.to_gradio_chatbot(),338        gr.MultimodalTextbox(interactive=True),339    ) + (enable_btn,) * 5340 341    finish_tstamp = time.time()342    logger.info(f"{finnal_output}")343    data = {344        "tstamp": round(finish_tstamp, 4),345        "like": None,346        "model": model_name,347        "start": round(start_tstamp, 4),348        "finish": round(start_tstamp, 4),349        "state": state.dict(),350        "images": all_image_paths,351        "ip": request.client.host,352    }353    write2file(get_log_filename(), json.dumps(data) + "\n")354 355# <h1 style="font-size: 28px; font-weight: bold;">Expanding Performance Boundaries of Open-Source Multimodal Models with Model, Data, and Test-Time Scaling</h1>356title_html = """357<img src="https://internvl.opengvlab.com/assets/logo-47b364d3.jpg" style="width: 280px; height: 70px;">358<p>InternVL2.5: Expanding Performance Boundaries of Open-Source Multimodal Models with Model, Data, and Test-Time Scaling</p>359<a href="https://internvl.github.io/blog/2024-12-05-InternVL-2.5/">[🆕 InternVL Blog]</a> 360<a href="https://huggingface.co/papers/2412.05271">[📖 InternVL Paper]</a>361<a href="https://github.com/OpenGVLab/InternVL">[🌟 Github]</a><br>362<a href="https://internvl.readthedocs.io/en/latest/">[📜 Document]</a>     363<a href="https://internvl.opengvlab.com/">[🗨️ Official Demo]</a> 364"""365 366 367tos_markdown = """368### Terms of use369By using this service, users are required to agree to the following terms:370The 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.371Please click the "Flag" button if you get any inappropriate answer! We will collect those to keep improving our moderator.372For an optimal experience, please use desktop computers for this demo, as mobile devices may compromise its quality.373"""374 375 376# .gradio-container {margin: 5px 10px 0 10px !important};377block_css = """378.gradio-container {margin: 0.1% 1% 0 1% !important; max-width: 98% !important;};379#buttons button {380    min-width: min(120px,100%);381}382 383.gradient-text {384    font-size: 28px;385    width: auto;386    font-weight: bold;387    background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet);388    background-clip: text;389    -webkit-background-clip: text;390    color: transparent;391}392 393.plain-text {394    font-size: 22px;395    width: auto;396    font-weight: bold;397}398"""399 400js = """401function createWaveAnimation() {402    const text = document.getElementById('text');403    var i = 0;404    setInterval(function() {405        const colors = [406            'red, orange, yellow, green, blue, indigo, violet, purple',407            'orange, yellow, green, blue, indigo, violet, purple, red',408            'yellow, green, blue, indigo, violet, purple, red, orange',409            'green, blue, indigo, violet, purple, red, orange, yellow',410            'blue, indigo, violet, purple, red, orange, yellow, green',411            'indigo, violet, purple, red, orange, yellow, green, blue',412            'violet, purple, red, orange, yellow, green, blue, indigo',413            'purple, red, orange, yellow, green, blue, indigo, violet',414        ];415        const angle = 45;416        const colorIndex = i % colors.length;417        text.style.background = `linear-gradient(${angle}deg, ${colors[colorIndex]})`;418        text.style.webkitBackgroundClip = 'text';419        text.style.backgroundClip = 'text';420        text.style.color = 'transparent';421        text.style.fontSize = '28px';422        text.style.width = 'auto';423        text.textContent = 'InternVL2';424        text.style.fontWeight = 'bold';425        i += 1;426    }, 200);427    const params = new URLSearchParams(window.location.search);428    url_params = Object.fromEntries(params);429    // console.log(url_params);430    // console.log('hello world...');431    // console.log(window.location.search);432    // console.log('hello world...');433    // alert(window.location.search)434    // alert(url_params);435    return url_params;436}437 438"""439 440 441def build_demo():442    textbox = gr.MultimodalTextbox(443        interactive=True,444        file_types=["image", "video"],445        placeholder="Enter message or upload file...",446        show_label=False,447    )448 449    with gr.Blocks(450        title="InternVL-Chat",451        theme=gr.themes.Default(),452        css=block_css,453    ) as demo:454        state = gr.State()455 456        with gr.Row():457            with gr.Column(scale=2):458                # gr.Image('./gallery/logo-47b364d3.jpg')459                gr.HTML(title_html)460 461                with gr.Accordion("Settings", open=False) as setting_row:462                    system_prompt = gr.Textbox(463                        value="请尽可能详细地回答用户的问题。",464                        label="System Prompt",465                        interactive=True,466                    )467                    temperature = gr.Slider(468                        minimum=0.0,469                        maximum=1.0,470                        value=0.2,471                        step=0.1,472                        interactive=True,473                        label="Temperature",474                    )475                    top_p = gr.Slider(476                        minimum=0.0,477                        maximum=1.0,478                        value=0.7,479                        step=0.1,480                        interactive=True,481                        label="Top P",482                    )483                    repetition_penalty = gr.Slider(484                        minimum=1.0,485                        maximum=1.5,486                        value=1.1,487                        step=0.02,488                        interactive=True,489                        label="Repetition penalty",490                    )491                    max_output_tokens = gr.Slider(492                        minimum=0,493                        maximum=4096,494                        value=1024,495                        step=64,496                        interactive=True,497                        label="Max output tokens",498                    )499                    max_input_tiles = gr.Slider(500                        minimum=1,501                        maximum=32,502                        value=12,503                        step=1,504                        interactive=True,505                        label="Max input tiles (control the image size)",506                    )507                examples = gr.Examples(508                    examples=[509                        [510                            {511                                "files": [512                                    "gallery/14.jfif",513                                ],514                                "text": "Please help me analyze this picture.",515                            }516                        ],517                        [518                            {519                                "files": [520                                    "gallery/1-2.PNG",521                                ],522                                "text": "Implement this flow chart using python",523                            }524                        ],525                        [526                            {527                                "files": [528                                    "gallery/15.PNG",529                                ],530                                "text": "Please help me analyze this picture.",531                            }532                        ],533                    ],534                    inputs=[textbox],535                )536 537            with gr.Column(scale=8):538                chatbot = gr.Chatbot(539                    elem_id="chatbot",540                    label="InternVL",541                    height=580,542                    show_copy_button=True,543                    show_share_button=True,544                    avatar_images=[545                        "assets/human.png",546                        "assets/assistant.png",547                    ],548                    bubble_full_width=False,549                )550                with gr.Row():551                    with gr.Column(scale=8):552                        textbox.render()553                    with gr.Column(scale=1, min_width=50):554                        submit_btn = gr.Button(value="Send", variant="primary")555                with gr.Row(elem_id="buttons") as button_row:556                    upvote_btn = gr.Button(value="👍  Upvote", interactive=False)557                    downvote_btn = gr.Button(value="👎  Downvote", interactive=False)558                    flag_btn = gr.Button(value="⚠️  Flag", interactive=False)559                    # stop_btn = gr.Button(value="⏹️  Stop Generation", interactive=False)560                    regenerate_btn = gr.Button(561                        value="🔄  Regenerate", interactive=False562                    )563                    clear_btn = gr.Button(value="🗑️  Clear", interactive=False)564 565        gr.Markdown(tos_markdown)566        url_params = gr.JSON(visible=False)567 568        # Register listeners569        btn_list = [upvote_btn, downvote_btn, flag_btn, regenerate_btn, clear_btn]570        upvote_btn.click(571            upvote_last_response,572            [state],573            [textbox, upvote_btn, downvote_btn, flag_btn],574        )575        downvote_btn.click(576            downvote_last_response,577            [state],578            [textbox, upvote_btn, downvote_btn, flag_btn],579        )580        chatbot.like(581            vote_selected_response,582            [state],583            [],584        )585        flag_btn.click(586            flag_last_response,587            [state],588            [textbox, upvote_btn, downvote_btn, flag_btn],589        )590        regenerate_btn.click(591            regenerate,592            [state, system_prompt],593            [state, chatbot, textbox] + btn_list,594        ).then(595            http_bot,596            [597                state,598                temperature,599                top_p,600                repetition_penalty,601                max_output_tokens,602                max_input_tiles,603            ],604            [state, chatbot, textbox] + btn_list,605        )606        clear_btn.click(clear_history, None, [state, chatbot, textbox] + btn_list)607 608        textbox.submit(609            add_text,610            [state, textbox, system_prompt],611            [state, chatbot, textbox] + btn_list,612        ).then(613            http_bot,614            [615                state,616                temperature,617                top_p,618                repetition_penalty,619                max_output_tokens,620                max_input_tiles,621            ],622            [state, chatbot, textbox] + btn_list,623        )624        submit_btn.click(625            add_text,626            [state, textbox, system_prompt],627            [state, chatbot, textbox] + btn_list,628        ).then(629            http_bot,630            [631                state,632                temperature,633                top_p,634                repetition_penalty,635                max_output_tokens,636                max_input_tiles,637            ],638            [state, chatbot, textbox] + btn_list,639        )640 641    return demo642 643 644if __name__ == "__main__":645    parser = argparse.ArgumentParser()646    parser.add_argument("--host", type=str, default="0.0.0.0")647    parser.add_argument("--port", type=int, default=7860)648    parser.add_argument("--concurrency-count", type=int, default=10)649    parser.add_argument("--share", action="store_true")650    parser.add_argument("--moderate", action="store_true")651    args = parser.parse_args()652    logger.info(f"args: {args}")653 654    logger.info(args)655    demo = build_demo()656    demo.queue(api_open=False).launch(657        server_name=args.host,658        server_port=args.port,659        share=args.share,660        max_threads=args.concurrency_count,661    )662