jerrychen428 commited on
Commit
ab9f810
·
verified ·
1 Parent(s): a2be545

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +290 -185
app.py CHANGED
@@ -1,35 +1,23 @@
1
  import os
 
2
  import base64
3
  from datetime import datetime
4
  from pathlib import Path
5
  import gradio as gr
6
  from google import genai
 
7
  import resend
8
- import html
9
- import logging
10
-
11
- # 設置日誌級別,以查看 Gradio 和底層庫的詳細資訊
12
- logging.basicConfig(level=logging.INFO)
13
 
14
  class GeminiImageAnalyzer:
15
- def __init__(self, gemini_api_key, resend_api_key):
16
- """初始化Gemini客戶端和Resend"""
17
- if not gemini_api_key:
18
- raise ValueError("未找到 Gemini API 金鑰。請將其設置為環境變數。")
19
- if not resend_api_key:
20
- raise ValueError("未找到 Resend API 金鑰。請將其設置為環境變數。")
21
-
22
- self.gemini_api_key = gemini_api_key
23
- # 使用提供的金鑰初始化 Gemini 客戶端
24
- genai.configure(api_key=gemini_api_key)
25
- self.client = genai.GenerativeModel(model_name="gemini-1.5-flash")
26
- # 使用提供的金鑰初始化 Resend
27
- resend.api_key = resend_api_key
28
 
29
  def validate_image(self, image_path):
30
  """驗證圖片格式和存在性"""
31
  if not os.path.exists(image_path):
32
- raise FileNotFoundError(f"圖片文件不存在: {image_path}")
33
 
34
  file_extension = Path(image_path).suffix.lower()
35
  if file_extension not in ['.jpg', '.jpeg', '.png']:
@@ -49,242 +37,359 @@ class GeminiImageAnalyzer:
49
  mime_type = "image/jpeg"
50
  elif file_extension == '.png':
51
  mime_type = "image/png"
52
- else:
53
- mime_type = "application/octet-stream" # 預設類型
54
 
55
  return encoded_string, mime_type
56
  except Exception as e:
57
  raise Exception(f"圖片編碼失敗: {str(e)}")
58
 
59
- def analyze_image(self, image_path, prompt):
60
  """使用Gemini API分析圖片"""
61
  try:
62
  # 驗證圖片
63
  self.validate_image(image_path)
64
- logging.info(f"成功驗證圖片: {image_path}")
65
 
66
  # 編碼圖片
67
  encoded_image, mime_type = self.encode_image(image_path)
68
- logging.info(f"圖片成功編碼為 {mime_type}")
69
 
70
  # 構建請求內容
71
- image_part = {
72
- "mime_type": mime_type,
73
- "data": base64.b64decode(encoded_image)
74
- }
75
-
76
- contents = [prompt, image_part]
 
 
 
 
 
 
 
 
77
 
78
  # 調用Gemini API
79
- response = self.client.generate_content(contents)
80
- logging.info("成功調用 Gemini API")
81
-
 
 
82
  return response.text
83
 
84
  except Exception as e:
85
- logging.error(f"分析失敗: {str(e)}")
86
  return f"分析失敗: {str(e)}"
87
 
88
- def send_analysis_email(self, analysis_result, recipient_email, subject="圖片分析結果"):
89
- """發送分析結果到指定郵箱"""
 
 
 
 
 
90
  try:
91
- # 將分析結果轉換為HTML格式
92
  html_content = f"""
93
  <html>
94
  <head>
95
- <meta charset="UTF-8">
96
- <title>圖片分析結果</title>
97
  <style>
98
- body {{ font-family: Arial, sans-serif; line-height: 1.6; color: #333; }}
99
- .container {{ max-width: 600px; margin: 20px auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }}
100
- h2 {{ color: #0056b3; }}
101
- .info-box {{ background-color: #f0f8ff; padding: 15px; border-radius: 5px; border-left: 4px solid #007bff; }}
102
- .footer {{ margin-top: 20px; font-size: 12px; color: #777; }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  </style>
104
  </head>
105
  <body>
106
- <div class="container">
107
- <h2>圖片分析結果</h2>
108
- <hr>
109
- <p><strong>分析時間:</strong>{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
110
- <h3>分析內容:</h3>
111
- <div class="info-box">
112
- {html.escape(analysis_result).replace('\n', '<br>')}
 
 
113
  </div>
114
- <p class="footer">此郵件由Gemini圖片分析系統自動發送</p>
 
 
 
115
  </div>
116
  </body>
117
  </html>
118
  """
119
-
120
  params = {
121
- "from": "Acme <onboarding@resend.dev>",
122
- "to": [recipient_email],
123
- "subject": subject,
124
- "html": html_content,
125
- "reply_to": "onboarding@resend.dev"
126
  }
127
 
128
- email_response = resend.Emails.send(params)
129
- logging.info(f"郵件發送成功!郵件ID: {email_response.get('id', 'Unknown')}")
130
- return f"郵件發送成功!郵件ID: {email_response.get('id', 'Unknown')}"
131
 
132
  except Exception as e:
133
- logging.error(f"郵件發送失敗: {str(e)}")
134
  return f"郵件發送失敗: {str(e)}"
135
 
136
- def create_gradio_app():
137
- """創建 Gradio 應用介面"""
138
- # 從環境變數中讀取 API 密鑰
139
- gemini_api_key = os.getenv("GEMINI_API_KEY")
140
- resend_api_key = os.getenv("RESEND_API_KEY")
141
 
142
- # 創建分析器實例
143
- analyzer = GeminiImageAnalyzer(gemini_api_key, resend_api_key)
 
 
 
 
 
 
 
 
 
 
144
 
145
- def process_image_and_send_email(image_file, prompt, recipient_email, email_subject, send_email_flag):
146
- """處理圖片分析並可選發送郵件"""
147
- try:
148
- if image_file is None:
149
- return "請先上傳圖片", ""
150
-
151
- # 使用默認提示詞如果為空
152
- if not prompt.strip():
153
- prompt = "請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
154
-
155
- # 分析圖片
156
- analysis_result = analyzer.analyze_image(image_file, prompt)
157
-
158
- email_status = ""
159
- if send_email_flag and recipient_email.strip():
160
- # 使用默認主題如果為空
161
- if not email_subject.strip():
162
- email_subject = "圖片分析結果"
163
-
164
- # 發送郵件
165
- email_status = analyzer.send_analysis_email(
166
- analysis_result,
167
- recipient_email.strip(),
168
- email_subject
169
- )
170
- elif send_email_flag and not recipient_email.strip():
171
- email_status = "請輸入收件人郵箱地址"
172
-
173
- return analysis_result, email_status
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
- except Exception as e:
176
- return f"處理失敗: {str(e)}", ""
 
 
 
 
 
 
 
 
 
177
 
178
- # 建Gradio介面
179
- with gr.Blocks(title="Gemini 圖片分析與郵件發送系統") as app:
180
- gr.Markdown("# 🔍 Gemini 圖片分析與郵件發送系統")
181
- gr.Markdown("上傳圖片進行AI分析,並可選擇將結果發送到指定")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
 
183
  with gr.Row():
184
  with gr.Column(scale=1):
185
- # 圖片上傳
186
  image_input = gr.Image(
 
187
  type="filepath",
188
- label="上傳圖片 (支援 JPG, PNG 格式)"
189
  )
190
 
191
- # 提示詞輸入
192
  prompt_input = gr.Textbox(
193
- label="分析提示詞",
194
  placeholder="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文",
195
  lines=3,
196
  value="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
197
  )
198
 
199
- # 郵件設定
200
- with gr.Group():
201
- gr.Markdown("### 📧 郵件設定")
202
- send_email_checkbox = gr.Checkbox(
203
- label="發送分析結果到郵箱",
204
- value=False
205
- )
206
- recipient_email = gr.Textbox(
207
- label="收件人郵箱",
208
- placeholder="example@example.com"
209
- )
210
- email_subject = gr.Textbox(
211
- label="郵件主題",
212
- placeholder="圖片分析結果",
213
- value="圖片分析結果"
214
- )
215
 
216
- # 分析按鈕
 
 
 
 
 
 
 
217
  analyze_btn = gr.Button(
218
- "🔍 開始分析",
219
  variant="primary",
220
  size="lg"
221
  )
222
-
223
- with gr.Column(scale=1):
224
- # 分析結果顯示
 
 
 
 
 
 
 
 
 
225
  analysis_output = gr.Textbox(
226
- label="分析結果",
227
- lines=15,
228
- max_lines=20,
229
- show_copy_button=True
230
  )
231
-
232
- # 郵件發送狀態
233
- email_status = gr.Textbox(
234
- label="郵件發送狀態",
235
- lines=2
 
236
  )
237
 
238
- # 使用說明
239
- with gr.Accordion("📖 使用說明", open=False):
240
- gr.Markdown("""
241
- ### 如何使用:
242
- 1. **上傳圖片**:點擊左側區域上傳 JPG 或 PNG 格式的圖片
243
- 2. **設定提示詞**:自訂分析要求,或使用預設提示詞
244
- 3. **郵件設定**(可選):
245
- - 勾選「發送分析結果到郵箱」
246
- - 輸入收件人郵箱地址
247
- - 自訂郵件主題
248
- 4. **開始分析**:點擊「開始分析」按鈕
249
- 5. **查看結果**:右側將顯示AI分析結果和郵件發送狀態
250
-
251
- ### 注意事項:
252
- - 支援的圖片格式:JPG, JPEG, PNG
253
- - 分析結果會以繁體中文顯示
254
- - 郵件功能為可選,不影響圖片分析功能
255
- """)
256
 
257
  # 綁定事件
258
  analyze_btn.click(
259
- fn=process_image_and_send_email,
260
- inputs=[
261
- image_input,
262
- prompt_input,
263
- recipient_email,
264
- email_subject,
265
- send_email_checkbox
266
- ],
267
- outputs=[analysis_output, email_status]
268
  )
269
 
270
- # 範例
271
- with gr.Accordion("💡 範例提示詞", open=False):
272
- examples = [
273
- "請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文",
274
- "這張圖片中有哪些物品?請列出所有看到的東西",
275
- "請分析這張圖片的色彩搭配和構圖特點",
276
- "圖片中有什麼文字內容?請完整轉錄出來",
277
- "這張圖片傳達了什麼情感或氛圍?"
278
- ]
279
-
280
- for example in examples:
281
- gr.Button(example, size="sm").click(
282
- lambda x=example: x,
283
- outputs=prompt_input
284
- )
285
-
286
- return app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
- # Hugging Face Spaces 上,應用會自動被 `app.py` 啟動,
289
- # 所以我們只需將主函數的啟動邏輯放在檔案的頂層。
290
- app = create_gradio_app()
 
 
 
 
 
 
 
1
  import os
2
+ import csv
3
  import base64
4
  from datetime import datetime
5
  from pathlib import Path
6
  import gradio as gr
7
  from google import genai
8
+ from PIL import Image
9
  import resend
 
 
 
 
 
10
 
11
  class GeminiImageAnalyzer:
12
+ def __init__(self, api_key):
13
+ """初始化Gemini客戶端"""
14
+ self.api_key = api_key
15
+ self.client = genai.Client(api_key=api_key)
 
 
 
 
 
 
 
 
 
16
 
17
  def validate_image(self, image_path):
18
  """驗證圖片格式和存在性"""
19
  if not os.path.exists(image_path):
20
+ raise FileNotFoundError(f"圖片檔案不存在: {image_path}")
21
 
22
  file_extension = Path(image_path).suffix.lower()
23
  if file_extension not in ['.jpg', '.jpeg', '.png']:
 
37
  mime_type = "image/jpeg"
38
  elif file_extension == '.png':
39
  mime_type = "image/png"
 
 
40
 
41
  return encoded_string, mime_type
42
  except Exception as e:
43
  raise Exception(f"圖片編碼失敗: {str(e)}")
44
 
45
+ def analyze_image(self, image_path, prompt="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"):
46
  """使用Gemini API分析圖片"""
47
  try:
48
  # 驗證圖片
49
  self.validate_image(image_path)
 
50
 
51
  # 編碼圖片
52
  encoded_image, mime_type = self.encode_image(image_path)
 
53
 
54
  # 構建請求內容
55
+ contents = [
56
+ {
57
+ "role": "user",
58
+ "parts": [
59
+ {"text": prompt},
60
+ {
61
+ "inline_data": {
62
+ "mime_type": mime_type,
63
+ "data": encoded_image
64
+ }
65
+ }
66
+ ]
67
+ }
68
+ ]
69
 
70
  # 調用Gemini API
71
+ response = self.client.models.generate_content(
72
+ model="gemini-2.0-flash-exp",
73
+ contents=contents
74
+ )
75
+
76
  return response.text
77
 
78
  except Exception as e:
 
79
  return f"分析失敗: {str(e)}"
80
 
81
+ class EmailSender:
82
+ def __init__(self, api_key):
83
+ """初始化Resend郵件客戶端"""
84
+ resend.api_key = api_key
85
+
86
+ def send_analysis_email(self, to_email, analysis_result, image_name="圖片"):
87
+ """發送分析結果郵件"""
88
  try:
89
+ # 構建HTML郵件內容
90
  html_content = f"""
91
  <html>
92
  <head>
 
 
93
  <style>
94
+ body {{
95
+ font-family: 'Microsoft JhengHei', Arial, sans-serif;
96
+ line-height: 1.6;
97
+ color: #333;
98
+ max-width: 800px;
99
+ margin: 0 auto;
100
+ padding: 20px;
101
+ }}
102
+ .header {{
103
+ background-color: #4CAF50;
104
+ color: white;
105
+ padding: 20px;
106
+ text-align: center;
107
+ border-radius: 5px;
108
+ margin-bottom: 20px;
109
+ }}
110
+ .content {{
111
+ background-color: #f9f9f9;
112
+ padding: 20px;
113
+ border-radius: 5px;
114
+ border-left: 4px solid #4CAF50;
115
+ }}
116
+ .timestamp {{
117
+ color: #666;
118
+ font-size: 0.9em;
119
+ margin-top: 20px;
120
+ text-align: right;
121
+ }}
122
  </style>
123
  </head>
124
  <body>
125
+ <div class="header">
126
+ <h1>🖼️ Gemini 圖片分析結果</h1>
127
+ </div>
128
+
129
+ <div class="content">
130
+ <h2>分析圖片:{image_name}</h2>
131
+ <p><strong>分析結果:</strong></p>
132
+ <div style="white-space: pre-wrap; background: white; padding: 15px; border-radius: 3px;">
133
+ {analysis_result}
134
  </div>
135
+ </div>
136
+
137
+ <div class="timestamp">
138
+ 產生時間:{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
139
  </div>
140
  </body>
141
  </html>
142
  """
143
+
144
  params = {
145
+ "from": "Gemini AI <onboarding@resend.dev>",
146
+ "to": [to_email],
147
+ "subject": f"🤖 圖片分析結果 - {image_name}",
148
+ "html": html_content
 
149
  }
150
 
151
+ email = resend.Emails.send(params)
152
+ return f"郵件發送成功!郵件ID: {email.get('id', 'N/A')}"
 
153
 
154
  except Exception as e:
 
155
  return f"郵件發送失敗: {str(e)}"
156
 
157
+ # 全域變數
158
+ analyzer = None
159
+ email_sender = None
 
 
160
 
161
+ def initialize_services(gemini_key, resend_key):
162
+ """初始化服務"""
163
+ global analyzer, email_sender
164
+
165
+ try:
166
+ if gemini_key:
167
+ analyzer = GeminiImageAnalyzer(gemini_key)
168
+ if resend_key:
169
+ email_sender = EmailSender(resend_key)
170
+ return "✅ 服務初始化成功!"
171
+ except Exception as e:
172
+ return f"❌ 服務初始化失敗: {str(e)}"
173
 
174
+ def analyze_and_send_email(image, prompt, recipient_email, gemini_key, resend_key):
175
+ """分析圖片並發送郵件"""
176
+ if image is None:
177
+ return "❌ 請先上傳圖片", "", ""
178
+
179
+ if not recipient_email:
180
+ return "❌ 請輸入收件人信箱", "", ""
181
+
182
+ if not gemini_key:
183
+ return "❌ 請輸入Gemini API Key", "", ""
184
+
185
+ if not resend_key:
186
+ return "❌ 請輸入Resend API Key", "", ""
187
+
188
+ try:
189
+ # 初始化服務
190
+ temp_analyzer = GeminiImageAnalyzer(gemini_key)
191
+ temp_email_sender = EmailSender(resend_key)
192
+
193
+ # 分析圖片
194
+ if not prompt.strip():
195
+ prompt = "請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
196
+
197
+ analysis_result = temp_analyzer.analyze_image(image, prompt)
198
+
199
+ if analysis_result.startswith("分析失敗"):
200
+ return f"❌ {analysis_result}", analysis_result, ""
201
+
202
+ # 發送郵件
203
+ image_name = os.path.basename(image) if isinstance(image, str) else "上傳的圖片"
204
+ email_result = temp_email_sender.send_analysis_email(
205
+ recipient_email,
206
+ analysis_result,
207
+ image_name
208
+ )
209
+
210
+ status = f"✅ 處理完成!\n📧 {email_result}"
211
+
212
+ return status, analysis_result, email_result
213
+
214
+ except Exception as e:
215
+ error_msg = f"❌ 處理失敗: {str(e)}"
216
+ return error_msg, "", ""
217
+
218
+ def save_result_to_csv(image_path, prompt, analysis_result):
219
+ """儲存結果到CSV"""
220
+ try:
221
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
222
+ csv_filename = f"analysis_result_{timestamp}.csv"
223
+
224
+ with open(csv_filename, 'w', newline='', encoding='utf-8-sig') as csvfile:
225
+ fieldnames = ['時間戳記', '圖片路徑', '使用者提示', '分析結果']
226
+ writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
227
 
228
+ writer.writeheader()
229
+ writer.writerow({
230
+ '時間戳記': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
231
+ '圖片路徑': image_path or "上傳的圖片",
232
+ '使用者提示': prompt,
233
+ '分析結果': analysis_result
234
+ })
235
+
236
+ return csv_filename
237
+ except Exception as e:
238
+ return f"儲存失敗: {str(e)}"
239
 
240
+ # 建Gradio介面
241
+ def create_interface():
242
+ with gr.Blocks(
243
+ title="🤖 Gemini 圖片分析郵件助手",
244
+ theme=gr.themes.Soft(),
245
+ css="""
246
+ .gradio-container {
247
+ max-width: 1000px !important;
248
+ margin: auto !important;
249
+ }
250
+ .main-header {
251
+ text-align: center;
252
+ margin-bottom: 2rem;
253
+ }
254
+ """
255
+ ) as demo:
256
+
257
+ gr.HTML("""
258
+ <div class="main-header">
259
+ <h1>🤖 Gemini 圖片分析郵件助手</h1>
260
+ <p>上傳圖片,AI分析內容,自動發送結果到您的信箱</p>
261
+ </div>
262
+ """)
263
 
264
  with gr.Row():
265
  with gr.Column(scale=1):
266
+ gr.Markdown("### 📁 圖片上傳")
267
  image_input = gr.Image(
268
+ label="選擇圖片",
269
  type="filepath",
270
+ height=300
271
  )
272
 
273
+ gr.Markdown("### ✏️ 分析設定")
274
  prompt_input = gr.Textbox(
275
+ label="自訂提示詞",
276
  placeholder="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文",
277
  lines=3,
278
  value="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
279
  )
280
 
281
+ recipient_email = gr.Textbox(
282
+ label="📧 收件人信箱",
283
+ placeholder="example@email.com"
284
+ )
285
+
286
+ with gr.Column(scale=1):
287
+ gr.Markdown("### 🔑 API設定")
288
+ gemini_key = gr.Textbox(
289
+ label="Gemini API Key",
290
+ placeholder="AIza...",
291
+ type="password",
292
+ value="AIzaSyCd8QuSZ45QeO0iP_yczjam--2Ri1sdJa4"
293
+ )
 
 
 
294
 
295
+ resend_key = gr.Textbox(
296
+ label="Resend API Key",
297
+ placeholder="re_...",
298
+ type="password",
299
+ value="re_fexD5RDm_LtvcVwyWphKQcjH9CEJ2Peus"
300
+ )
301
+
302
+ gr.Markdown("### 🚀 執行操作")
303
  analyze_btn = gr.Button(
304
+ "🔍 分析圖片並發送郵件",
305
  variant="primary",
306
  size="lg"
307
  )
308
+
309
+ gr.Markdown("### 📊 處理結果")
310
+
311
+ with gr.Row():
312
+ status_output = gr.Textbox(
313
+ label="📈 處理狀態",
314
+ lines=3,
315
+ interactive=False
316
+ )
317
+
318
+ with gr.Row():
319
+ with gr.Column():
320
  analysis_output = gr.Textbox(
321
+ label="🤖 AI分析結果",
322
+ lines=10,
323
+ interactive=False
 
324
  )
325
+
326
+ with gr.Column():
327
+ email_output = gr.Textbox(
328
+ label="📧 郵件發送結果",
329
+ lines=10,
330
+ interactive=False
331
  )
332
 
333
+ with gr.Row():
334
+ download_btn = gr.Button("💾 下載CSV結果", variant="secondary")
335
+ csv_file = gr.File(label="CSV檔案", visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
 
337
  # 綁定事件
338
  analyze_btn.click(
339
+ fn=analyze_and_send_email,
340
+ inputs=[image_input, prompt_input, recipient_email, gemini_key, resend_key],
341
+ outputs=[status_output, analysis_output, email_output]
 
 
 
 
 
 
342
  )
343
 
344
+ def download_csv(image_path, prompt, analysis_result):
345
+ if analysis_result:
346
+ filename = save_result_to_csv(image_path, prompt, analysis_result)
347
+ return gr.File.update(value=filename, visible=True)
348
+ return gr.File.update(visible=False)
349
+
350
+ download_btn.click(
351
+ fn=download_csv,
352
+ inputs=[image_input, prompt_input, analysis_output],
353
+ outputs=csv_file
354
+ )
355
+
356
+ # 新增範例
357
+ gr.Markdown("### 📝 使用說明")
358
+ gr.Markdown("""
359
+ 1. **上傳圖片**: 支援 JPG、JPEG、PNG 格式
360
+ 2. **設定API**: 輸入您的 Gemini 和 Resend API Keys
361
+ 3. **設定信箱**: 輸入接收分析結果的信箱地址
362
+ 4. **自訂提示**: 可選,自訂AI分析的重點
363
+ 5. **執行分析**: 點擊按鈕開始處理
364
+ 6. **檢視結果**: 在下方檢視分析結果和郵件發送狀態
365
+ 7. **下載CSV**: 可選,下載結果檔案儲存
366
+
367
+ **注意**: 請確保您的API Keys有效且有足夠的配額。
368
+ """)
369
+
370
+ # 新增範例圖片區域
371
+ gr.Markdown("### 🎯 使用範例")
372
+ with gr.Row():
373
+ gr.Examples(
374
+ examples=[
375
+ ["請分析這張圖片中的文字內容"],
376
+ ["這張圖片裡有什麼物品?請詳細列出"],
377
+ ["請描述圖片中人物的動作和表情"],
378
+ ["提取圖片中的所有文字,並翻譯成英文"],
379
+ ["分析這張圖片的構圖和色彩搭配"]
380
+ ],
381
+ inputs=prompt_input,
382
+ label="常用提示詞範例"
383
+ )
384
+
385
+ return demo
386
 
387
+ if __name__ == "__main__":
388
+ # 建立並啟動介面
389
+ demo = create_interface()
390
+ demo.launch(
391
+ server_name="0.0.0.0",
392
+ server_port=7860,
393
+ share=True,
394
+ show_error=True
395
+ )