File size: 5,513 Bytes
45c93b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# pip install -U transformers gradio pillow torchvision

import torch
import gradio as gr
from transformers import AutoProcessor, AutoModelForImageTextToText

# โ”€โ”€ ่ผ‰ๅ…ฅๆจกๅž‹ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
MODEL_ID = "google/gemma-4-12B"

print(f"่ผ‰ๅ…ฅๆจกๅž‹๏ผš{MODEL_ID} ...")
processor = AutoProcessor.from_pretrained(MODEL_ID)
model = AutoModelForImageTextToText.from_pretrained(
    MODEL_ID,
    dtype=torch.float16,   # torch_dtype ๅทฒๆฃ„็”จ๏ผŒๆ”น็”จ dtype
    device_map="auto",
)
model.eval()
print("ๆจกๅž‹่ผ‰ๅ…ฅๅฎŒๆˆ๏ผ")


# โ”€โ”€ ๆŽจ่ซ–ๅ‡ฝๅผ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def build_messages(history: list, user_text: str, image=None) -> list:
    """ๅฐ‡ Gradio tuples ๆญทๅฒ่ฝ‰ๆ›ๆˆ HuggingFace messages ๆ ผๅผใ€‚"""
    messages = []
    for user_turn, assistant_turn in history:
        messages.append({"role": "user",      "content": [{"type": "text", "text": user_turn or ""}]})
        messages.append({"role": "assistant", "content": [{"type": "text", "text": assistant_turn or ""}]})

    user_content = []
    if image is not None:
        user_content.append({"type": "image", "image": image})
    user_content.append({"type": "text", "text": user_text})
    messages.append({"role": "user", "content": user_content})
    return messages


def chat(user_message, image, history, max_new_tokens, temperature, top_p):
    """ไธปๅฐ่ฉฑๅ‡ฝๅผใ€‚history ็‚บ list of [user, assistant] tuplesใ€‚"""
    if not (user_message and user_message.strip()) and image is None:
        return history, history, "", None

    messages = build_messages(history, user_message, image)

    pil_images = [image] if image is not None else None
    inputs = processor.apply_chat_template(
        messages,
        add_generation_prompt=True,
        tokenize=True,
        return_tensors="pt",
        return_dict=True,
        images=pil_images,
    ).to(model.device, dtype=torch.float16)

    with torch.inference_mode():
        output_ids = model.generate(
            **inputs,
            max_new_tokens=int(max_new_tokens),
            do_sample=temperature > 0,
            temperature=float(temperature) if temperature > 0 else 1.0,
            top_p=float(top_p),
        )

    input_len = inputs["input_ids"].shape[-1]
    response = processor.decode(
        output_ids[0, input_len:], skip_special_tokens=True
    ).strip()

    history = history + [[user_message, response]]
    return history, history, "", None


def clear_history():
    return [], [], "", None


# โ”€โ”€ Gradio UI๏ผˆGradio 6 ็›ธๅฎน๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
CSS = """
    #chatbot { height: 550px; }
    .send-btn { background: #10b981 !important; color: white !important; }
    footer { display: none !important; }
"""

with gr.Blocks(title="Gemma-4 Chat") as demo:
    gr.Markdown(
        """
        # ๐Ÿค– Gemma-4 ๅคšๆจกๆ…‹ๅฐ่ฉฑๅŠฉ็†
        ๆ”ฏๆด็ด”ๆ–‡ๅญ—ๅฐ่ฉฑ๏ผŒไบฆๅฏไธŠๅ‚ณๅœ–็‰‡้€ฒ่กŒๅœ–ๆ–‡ๅ•็ญ”ใ€‚
        """
    )

    state = gr.State([])

    with gr.Row():
        with gr.Column(scale=3):
            chatbot = gr.Chatbot(
                elem_id="chatbot",
                label="ๅฐ่ฉฑ่ฆ–็ช—",
                # Gradio 6 ไธๆ”ฏๆด type="messages"๏ผ›ไฝฟ็”จ้ ่จญ tuples ๆ ผๅผ
            )
            with gr.Row():
                user_input = gr.Textbox(
                    placeholder="่ผธๅ…ฅ่จŠๆฏ๏ผŒๆŒ‰ Enter ๆˆ–้ปžๆ“Š้€ๅ‡บโ€ฆ",
                    show_label=False,
                    lines=2,
                    scale=5,
                )
                send_btn = gr.Button("้€ๅ‡บ โ–ถ", elem_classes="send-btn", scale=1)

        with gr.Column(scale=1):
            image_input = gr.Image(
                label="ไธŠๅ‚ณๅœ–็‰‡๏ผˆ้ธๅกซ๏ผ‰",
                type="pil",
                height=220,
            )
            gr.Markdown("### โš™๏ธ ็”Ÿๆˆๅƒๆ•ธ")
            max_new_tokens = gr.Slider(64, 2048, value=512, step=64,  label="ๆœ€ๅคง็”Ÿๆˆ้•ทๅบฆ")
            temperature    = gr.Slider(0.0, 2.0,  value=0.7, step=0.05, label="Temperature๏ผˆ0 = ็ขบๅฎšๆ€ง๏ผ‰")
            top_p          = gr.Slider(0.1, 1.0,  value=0.9, step=0.05, label="Top-p")
            clear_btn = gr.Button("๐Ÿ—‘๏ธ ๆธ…้™คๅฐ่ฉฑ", variant="secondary")

    send_inputs  = [user_input, image_input, state, max_new_tokens, temperature, top_p]
    send_outputs = [chatbot, state, user_input, image_input]

    send_btn.click(chat, inputs=send_inputs, outputs=send_outputs)
    user_input.submit(chat, inputs=send_inputs, outputs=send_outputs)
    clear_btn.click(clear_history, outputs=[chatbot, state, user_input, image_input])

# โ”€โ”€ ๅ•Ÿๅ‹• โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
if __name__ == "__main__":
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        share=False,        # Colab ่ซ‹ๆ”น True
        inbrowser=True,
        theme=gr.themes.Soft(primary_hue="emerald"),  # Gradio 6: theme ็งปๅˆฐ launch()
        css=CSS,
    )