AdrianLi33 commited on
Commit
028cff0
ยท
verified ยท
1 Parent(s): 5255084

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -0
app.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!pip install -U transformers gradio pillow
2
+
3
+ import torch
4
+ import gradio as gr
5
+ from transformers import AutoProcessor, AutoModelForImageTextToText
6
+ from PIL import Image
7
+
8
+ # โ”€โ”€ ่ผ‰ๅ…ฅๆจกๅž‹ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
9
+ MODEL_ID = "google/gemma-4-12B"
10
+
11
+ print(f"่ผ‰ๅ…ฅๆจกๅž‹๏ผš{MODEL_ID} ...")
12
+ processor = AutoProcessor.from_pretrained(MODEL_ID)
13
+ model = AutoModelForImageTextToText.from_pretrained(
14
+ MODEL_ID,
15
+ torch_dtype=torch.float16,
16
+ device_map="auto",
17
+ )
18
+ model.eval()
19
+ print("ๆจกๅž‹่ผ‰ๅ…ฅๅฎŒๆˆ๏ผ")
20
+
21
+
22
+ # โ”€โ”€ ๆŽจ่ซ–ๅ‡ฝๅผ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
23
+ def build_messages(history: list[dict], user_text: str, image=None) -> list[dict]:
24
+ """ๅฐ‡ Gradio ๆญทๅฒ่จ˜้Œ„่ฝ‰ๆ›ๆˆ HuggingFace messages ๆ ผๅผใ€‚"""
25
+ messages = []
26
+
27
+ # ๅŠ ๅ…ฅๆญทๅฒๅฐ่ฉฑ
28
+ for turn in history:
29
+ messages.append({"role": "user", "content": [{"type": "text", "text": turn["content"] if turn["role"] == "user" else ""}]})
30
+ messages.append({"role": "assistant", "content": [{"type": "text", "text": turn["content"] if turn["role"] == "assistant" else ""}]})
31
+
32
+ # ๅŠ ๅ…ฅๆœฌ่ผชไฝฟ็”จ่€…่จŠๆฏ
33
+ user_content = []
34
+ if image is not None:
35
+ user_content.append({"type": "image", "image": image})
36
+ user_content.append({"type": "text", "text": user_text})
37
+ messages.append({"role": "user", "content": user_content})
38
+
39
+ return messages
40
+
41
+
42
+ def chat(
43
+ user_message: str,
44
+ image,
45
+ history: list[dict],
46
+ max_new_tokens: int,
47
+ temperature: float,
48
+ top_p: float,
49
+ ):
50
+ """ไธปๅฐ่ฉฑๅ‡ฝๅผ๏ผŒๅ›žๅ‚ณๆ›ดๆ–ฐๅพŒ็š„ๆญทๅฒ่ˆ‡ๆธ…็ฉบ็š„่ผธๅ…ฅใ€‚"""
51
+ if not user_message.strip() and image is None:
52
+ return history, history, gr.update(value=""), gr.update(value=None)
53
+
54
+ # ๅปบๆง‹ messages
55
+ messages = build_messages(history, user_message, image)
56
+
57
+ # Processor ๅ‰่™•็†
58
+ pil_images = [image] if image is not None else None
59
+ inputs = processor.apply_chat_template(
60
+ messages,
61
+ add_generation_prompt=True,
62
+ tokenize=True,
63
+ return_tensors="pt",
64
+ return_dict=True,
65
+ images=pil_images,
66
+ ).to(model.device, dtype=torch.float16)
67
+
68
+ # ็”Ÿๆˆๅ›ž่ฆ†
69
+ with torch.inference_mode():
70
+ output_ids = model.generate(
71
+ **inputs,
72
+ max_new_tokens=max_new_tokens,
73
+ do_sample=temperature > 0,
74
+ temperature=temperature if temperature > 0 else 1.0,
75
+ top_p=top_p,
76
+ )
77
+
78
+ # ๅชๅ–ๆ–ฐ็”Ÿๆˆ็š„้ƒจๅˆ†
79
+ input_len = inputs["input_ids"].shape[-1]
80
+ generated_ids = output_ids[:, input_len:]
81
+ response = processor.decode(generated_ids[0], skip_special_tokens=True).strip()
82
+
83
+ # ๆ›ดๆ–ฐๆญทๅฒ๏ผˆไฝฟ็”จ Gradio messages ๆ ผๅผ๏ผ‰
84
+ history = history + [
85
+ {"role": "user", "content": user_message},
86
+ {"role": "assistant", "content": response},
87
+ ]
88
+
89
+ return history, history, gr.update(value=""), gr.update(value=None)
90
+
91
+
92
+ def clear_history():
93
+ return [], [], gr.update(value=""), gr.update(value=None)
94
+
95
+
96
+ # โ”€โ”€ Gradio UI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
97
+ with gr.Blocks(
98
+ title="Gemma-4 Chat",
99
+ theme=gr.themes.Soft(primary_hue="emerald"),
100
+ css="""
101
+ #chatbot { height: 550px; }
102
+ .send-btn { background: #10b981 !important; color: white !important; }
103
+ footer { display: none !important; }
104
+ """,
105
+ ) as demo:
106
+ # โ”€โ”€ ๆจ™้กŒ โ”€โ”€
107
+ gr.Markdown(
108
+ """
109
+ # ๐Ÿค– Gemma-4 ๅคšๆจกๆ…‹ๅฐ่ฉฑๅŠฉ็†
110
+ ๆ”ฏๆด็ด”ๆ–‡ๅญ—ๅฐ่ฉฑ๏ผŒไบฆๅฏไธŠๅ‚ณๅœ–็‰‡้€ฒ่กŒๅœ–ๆ–‡ๅ•็ญ”ใ€‚
111
+ """
112
+ )
113
+
114
+ # โ”€โ”€ ๅฐ่ฉฑ็‹€ๆ…‹ โ”€โ”€
115
+ state = gr.State([]) # ๅ„ฒๅญ˜ messages ๆญทๅฒ
116
+
117
+ with gr.Row():
118
+ # โ”€โ”€ ๅทฆๆฌ„๏ผš่Šๅคฉ่ฆ–็ช— โ”€โ”€
119
+ with gr.Column(scale=3):
120
+ chatbot = gr.Chatbot(
121
+ elem_id="chatbot",
122
+ label="ๅฐ่ฉฑ่ฆ–็ช—",
123
+ type="messages", # ไฝฟ็”จ dict ๆ ผๅผ
124
+ avatar_images=(None, "https://huggingface.co/datasets/huggingface/brand-assets/resolve/main/hf-logo.svg"),
125
+ )
126
+ with gr.Row():
127
+ user_input = gr.Textbox(
128
+ placeholder="่ผธๅ…ฅ่จŠๆฏ๏ผŒๆŒ‰ Enter ๆˆ–้ปžๆ“Š้€ๅ‡บโ€ฆ",
129
+ show_label=False,
130
+ lines=2,
131
+ scale=5,
132
+ )
133
+ send_btn = gr.Button("้€ๅ‡บ โ–ถ", elem_classes="send-btn", scale=1)
134
+
135
+ # โ”€โ”€ ๅณๆฌ„๏ผš่จญๅฎš่ˆ‡ๅœ–็‰‡ไธŠๅ‚ณ โ”€โ”€
136
+ with gr.Column(scale=1):
137
+ image_input = gr.Image(
138
+ label="ไธŠๅ‚ณๅœ–็‰‡๏ผˆ้ธๅกซ๏ผ‰",
139
+ type="pil",
140
+ height=220,
141
+ )
142
+ gr.Markdown("### โš™๏ธ ็”Ÿๆˆๅƒๆ•ธ")
143
+ max_new_tokens = gr.Slider(64, 2048, value=512, step=64, label="ๆœ€ๅคง็”Ÿๆˆ้•ทๅบฆ")
144
+ temperature = gr.Slider(0.0, 2.0, value=0.7, step=0.05, label="Temperature๏ผˆ0 = ็ขบๅฎšๆ€ง๏ผ‰")
145
+ top_p = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-p")
146
+ clear_btn = gr.Button("๐Ÿ—‘๏ธ ๆธ…้™คๅฐ่ฉฑ", variant="secondary")
147
+
148
+ # โ”€โ”€ ไบ‹ไปถ็ถๅฎš โ”€โ”€
149
+ send_inputs = [user_input, image_input, state, max_new_tokens, temperature, top_p]
150
+ send_outputs = [chatbot, state, user_input, image_input]
151
+
152
+ send_btn.click(chat, inputs=send_inputs, outputs=send_outputs)
153
+ user_input.submit(chat, inputs=send_inputs, outputs=send_outputs)
154
+ clear_btn.click(clear_history, outputs=[chatbot, state, user_input, image_input])
155
+
156
+ # โ”€โ”€ ๅ•Ÿๅ‹• โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
157
+ if __name__ == "__main__":
158
+ demo.launch(
159
+ server_name="0.0.0.0", # ๅ…่จฑๅค–้ƒจ้€ฃ็ทš๏ผˆColab / ้ ็ซฏไผบๆœๅ™จ็”จ๏ผ‰
160
+ server_port=7860,
161
+ share=False, # ่จญ็‚บ True ๅฏ็”ข็”Ÿๅ…ฌ้–‹้€ฃ็ต๏ผˆColab ้œ€่ฆ๏ผ‰
162
+ inbrowser=True,
163
+ )