import os
import csv
import base64
from datetime import datetime
from pathlib import Path
import gradio as gr
import google.generativeai as genai
from PIL import Image
import resend
import tempfile
import json
class GeminiImageAnalyzer:
def __init__(self, api_key):
"""初始化Gemini客戶端"""
self.api_key = api_key
# 正確的配置方式
genai.configure(api_key=api_key)
# 創建模型實例
self.model = genai.GenerativeModel('gemini-2.0-flash-exp')
def validate_image(self, image_path):
"""驗證圖片格式和存在性"""
if not os.path.exists(image_path):
raise FileNotFoundError(f"圖片檔案不存在: {image_path}")
file_extension = Path(image_path).suffix.lower()
if file_extension not in ['.jpg', '.jpeg', '.png', '.gif', '.webp']:
raise ValueError("支援 .jpg, .jpeg, .png, .gif, .webp 格式的圖片")
return True
def analyze_single_image(self, image_path, prompt="請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"):
"""分析單張圖片"""
try:
# 驗證圖片
self.validate_image(image_path)
# 直接使用PIL打開圖片
image = Image.open(image_path)
# 調用Gemini API的正確方式
response = self.model.generate_content([prompt, image])
return response.text
except Exception as e:
return f"分析失敗: {str(e)}"
def analyze_multiple_images(self, image_paths, comparison_prompt=None):
"""分析多張圖片並進行比較"""
try:
if not image_paths or len(image_paths) == 0:
return "❌ 請至少上傳一張圖片"
# 如果只有一張圖片,使用單圖片分析
if len(image_paths) == 1:
return self.analyze_single_image(
image_paths[0],
comparison_prompt or "請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
)
# 多圖片分析
images = []
image_info = []
for i, image_path in enumerate(image_paths):
# 驗證圖片
self.validate_image(image_path)
# 打開圖片
image = Image.open(image_path)
images.append(image)
image_info.append(f"圖片 {i+1}: {os.path.basename(image_path)}")
# 構建比較提示詞
if not comparison_prompt:
comparison_prompt = f"""
請詳細分析和比較這 {len(images)} 張圖片。請從以下方面進行分析:
1. **個別圖片描述**:
- 分別描述每張圖片的主要內容
- 識別每張圖片中的文字、物品、人物等
2. **相似之處**:
- 找出圖片之間的共同點
- 相同的元素、主題、風格等
3. **差異比較**:
- 指出圖片之間的明顯差異
- 不同的顏色、構圖、內容、角度等
4. **整體總結**:
- 這些圖片可能的關聯性
- 整體給人的印象或傳達的訊息
請使用繁體中文回答,條理清晰地組織你的分析。
"""
# 準備內容列表
content_parts = [comparison_prompt]
content_parts.extend(images)
# 調用API進行比較分析
response = self.model.generate_content(content_parts)
return response.text
except Exception as e:
return f"多圖片分析失敗: {str(e)}"
def batch_analyze_images(self, image_paths, individual_prompt=None):
"""批量分析圖片(每張圖片單獨分析)"""
try:
if not image_paths or len(image_paths) == 0:
return "❌ 請至少上傳一張圖片"
results = {}
individual_prompt = individual_prompt or "請詳細描述這張圖片的內容,並提取圖片中的文字,使用繁體中文"
for i, image_path in enumerate(image_paths):
image_name = os.path.basename(image_path)
print(f"正在分析圖片 {i+1}/{len(image_paths)}: {image_name}")
result = self.analyze_single_image(image_path, individual_prompt)
results[f"圖片 {i+1} ({image_name})"] = result
# 格式化輸出
formatted_result = "📊 **批量圖片分析結果**\n\n"
for image_key, analysis in results.items():
formatted_result += f"## {image_key}\n\n{analysis}\n\n---\n\n"
return formatted_result
except Exception as e:
return f"批量分析失敗: {str(e)}"
class MultiClientEmailSender:
def __init__(self):
"""初始化多客戶郵件發送器"""
self.email_clients = {}
def add_client(self, client_name, recipient_email, resend_api_key):
"""添加客戶端配置(包含專屬的Resend API Key)"""
self.email_clients[client_name] = {
'email': recipient_email,
'api_key': resend_api_key
}
def send_analysis_email(self, client_name, analysis_result, image_count=1, analysis_type="單圖片分析"):
"""向指定客戶發送分析結果郵件"""
try:
if client_name not in self.email_clients:
return f"❌ 客戶 {client_name} 未配置"
client_config = self.email_clients[client_name]
# 為每個客戶設定專屬的Resend API Key
resend.api_key = client_config['api_key']
# 構建HTML郵件內容
html_content = f"""
👤 專屬客戶:{client_name} | 📧 收件人:{client_config['email']}
📋 分析類型:{analysis_type} | 📸 圖片數量:{image_count} 張
🔍 分析結果
{analysis_result}
🕐 產生時間:{datetime.now().strftime("%Y年%m月%d日 %H:%M:%S")}
🚀 Powered by Google Gemini 2.0 & Resend
📋 專屬報告 for {client_name}
🔑 使用專屬 API Key:{client_config['api_key'][:8]}...
"""
params = {
"from": f"Gemini AI ",
"to": [client_config['email']],
"subject": f"🤖 AI圖片分析結果 - {client_name} - {analysis_type} ({image_count}張圖片)",
"html": html_content
}
email = resend.Emails.send(params)
api_key_display = client_config['api_key'][:8] + '...'
return f"✅ 發送成功!客戶:{client_name}(API: {api_key_display}),郵件ID: {email.get('id', 'N/A')}"
except Exception as e:
api_key_display = self.email_clients[client_name]['api_key'][:8] + '...' if client_name in self.email_clients else 'N/A'
return f"❌ 發送失敗({client_name}, API: {api_key_display}): {str(e)}"
def send_to_all_clients(self, analysis_result, image_count=1, analysis_type="單圖片分析"):
"""向所有客戶發送郵件"""
results = []
for client_name in self.email_clients.keys():
result = self.send_analysis_email(client_name, analysis_result, image_count, analysis_type)
results.append(result)
return results
def parse_client_configs(config_text):
"""解析客戶配置文本(包含專屬的Resend API Key)"""
clients = []
if not config_text.strip():
return clients
lines = config_text.strip().split('\n')
for line_num, line in enumerate(lines, 1):
line = line.strip()
if not line or line.startswith('#'): # 忽略空行和註釋行
continue
parts = line.split('|')
if len(parts) != 3:
raise ValueError(f"第{line_num}行格式錯誤:'{line}'\n正確格式:客戶名稱|郵箱|Resend API Key")
client_name = parts[0].strip()
email = parts[1].strip()
api_key = parts[2].strip()
if not client_name or not email or not api_key:
raise ValueError(f"第{line_num}行有空白欄位:'{line}'")
# 簡單的郵箱格式驗證
if '@' not in email or '.' not in email.split('@')[1]:
raise ValueError(f"第{line_num}行郵箱格式錯誤:'{email}'")
# Resend API Key 格式驗證
if not api_key.startswith('re_'):
raise ValueError(f"第{line_num}行 Resend API Key 格式錯誤:'{api_key}' (應以 're_' 開頭)")
clients.append({
'name': client_name,
'email': email,
'api_key': api_key
})
return clients
def analyze_images_and_send_emails(images, analysis_mode, custom_prompt, client_configs, gemini_key):
"""分析圖片並向多個客戶發送郵件"""
if not images or len(images) == 0:
return "❌ 請至少上傳一張圖片", "", ""
if not client_configs.strip():
return "❌ 請輸入至少一個客戶配置", "", ""
if not gemini_key:
return "❌ 請輸入Gemini API Key", "", ""
try:
# 解析客戶配置
clients = parse_client_configs(client_configs)
if not clients:
return "❌ 沒有有效的客戶配置", "", ""
# 初始化服務
analyzer = GeminiImageAnalyzer(gemini_key)
email_sender = MultiClientEmailSender()
# 添加所有客戶配置(包含專屬API Key)
for client in clients:
email_sender.add_client(client['name'], client['email'], client['api_key'])
# 獲取圖片路徑列表
image_paths = images if isinstance(images, list) else [images]
image_count = len(image_paths)
# 根據分析模式選擇分析方法
if analysis_mode == "比較分析":
analysis_result = analyzer.analyze_multiple_images(image_paths, custom_prompt)
analysis_type = "多圖片比較分析"
elif analysis_mode == "批量分析":
analysis_result = analyzer.batch_analyze_images(image_paths, custom_prompt)
analysis_type = "批量個別分析"
else: # 單張分析
if len(image_paths) > 1:
# 如果上傳多張但選擇單張分析,只分析第一張
analysis_result = analyzer.analyze_single_image(image_paths[0], custom_prompt)
analysis_type = "單圖片分析(僅分析第一張)"
image_count = 1
else:
analysis_result = analyzer.analyze_single_image(image_paths[0], custom_prompt)
analysis_type = "單圖片分析"
if analysis_result.startswith(("分析失敗", "多圖片分析失敗", "批量分析失敗", "❌")):
return f"❌ {analysis_result}", analysis_result, ""
# 向所有客戶發送郵件
email_results = email_sender.send_to_all_clients(analysis_result, image_count, analysis_type)
# 統計發送結果
success_count = sum(1 for result in email_results if result.startswith("✅"))
total_count = len(email_results)
status = f"""✅ 處理完成!
📊 分析模式:{analysis_type}
📸 處理圖片:{image_count} 張
👥 客戶數量:{total_count} 個
📧 發送成功:{success_count}/{total_count}
🔑 使用客戶專屬 API Keys
📋 詳細結果:
{chr(10).join(email_results)}"""
email_summary = "\n".join(email_results)
return status, analysis_result, email_summary
except ValueError as e:
error_msg = f"❌ 配置錯誤: {str(e)}"
return error_msg, "", ""
except Exception as e:
error_msg = f"❌ 處理失敗: {str(e)}"
return error_msg, "", ""
def save_results_to_csv(images, analysis_mode, custom_prompt, analysis_result, client_configs):
"""儲存結果到CSV"""
try:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
temp_dir = tempfile.gettempdir()
csv_filename = os.path.join(temp_dir, f"multi_client_analysis_{timestamp}.csv")
with open(csv_filename, 'w', newline='', encoding='utf-8-sig') as csvfile:
fieldnames = ['時間戳記', '分析模式', '圖片數量', '圖片列表', '自訂提示', '客戶數量', '客戶清單', '分析結果']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
# 處理圖片列表
if images:
image_list = [os.path.basename(img) if isinstance(img, str) else f"圖片_{i+1}"
for i, img in enumerate(images)]
image_names = "; ".join(image_list)
image_count = len(images)
else:
image_names = "無"
image_count = 0
# 處理客戶配置
try:
clients = parse_client_configs(client_configs)
client_list = "; ".join([f"{client['name']}({client['email']})" for client in clients])
client_count = len(clients)
except:
client_list = "配置解析失敗"
client_count = 0
writer.writerow({
'時間戳記': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'分析模式': analysis_mode,
'圖片數量': image_count,
'圖片列表': image_names,
'自訂提示': custom_prompt or "預設提示",
'客戶數量': client_count,
'客戶清單': client_list,
'分析結果': analysis_result
})
return csv_filename
except Exception as e:
return f"儲存失敗: {str(e)}"
# 建立Gradio介面
def create_interface():
with gr.Blocks(
title="🤖 Gemini 多客戶圖片分析系統 - 專屬API版",
theme=gr.themes.Soft(),
css="""
.gradio-container {
max-width: 1400px !important;
margin: auto !important;
}
.main-header {
text-align: center;
margin-bottom: 2rem;
padding: 1.5rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.api-warning {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
border: 1px solid #ffeaa7;
border-radius: 10px;
padding: 15px;
margin: 15px 0;
color: #856404;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.feature-highlight {
background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%);
border: 2px solid #4caf50;
border-radius: 10px;
padding: 15px;
margin: 15px 0;
color: #2e7d32;
}
.client-config-area {
background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%);
border: 2px solid #9c27b0;
border-radius: 10px;
padding: 15px;
margin: 15px 0;
}
"""
) as demo:
gr.HTML("""
🤖 Gemini 多客戶圖片分析系統
專屬API Key版本 - 每個客戶使用專屬的Resend API
🚀 部署於 Hugging Face Spaces | 🔥 支援最新 Gemini 2.0 | 🔑 客戶專屬API管理
""")
# 新功能亮點
gr.HTML("""
🎯 專屬API版本功能亮點:
- 👥 多客戶支援:一次分析,同時發送給多個客戶
- 🔑 專屬API配置:每個客戶使用專屬的Resend API Key
- 📧 個性化郵件:每封郵件都標註專屬客戶資訊和API來源
- 💰 獨立計費:每個客戶的API使用量獨立計算
- 🔐 安全隔離:客戶間的API Key完全隔離,提升安全性
- 📊 詳細追蹤:顯示每個客戶使用的API Key資訊
""")
# API 安全提醒
gr.HTML("""
⚠️ 專屬API版本重要提醒:
• 每個客戶需要配置專屬的 Resend API Key
• 客戶的 API Key 使用量和費用完全獨立
• 請確保每個 API Key 都有足夠的發送配額
• 建議客戶自行管理和監控API使用量
• 此應用程式不會永久儲存任何 API 密鑰
• 提供更高的安全性和使用量透明度
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 📁 圖片上傳")
images_input = gr.File(
label="選擇圖片 (支援多張上傳)",
file_count="multiple",
file_types=["image"],
height=200
)
# 顯示上傳的圖片預覽
images_gallery = gr.Gallery(
label="圖片預覽",
show_label=True,
elem_id="gallery",
columns=3,
rows=2,
height=300,
object_fit="contain"
)
gr.Markdown("### 🎯 分析模式")
analysis_mode = gr.Radio(
choices=["單張分析", "比較分析", "批量分析"],
value="比較分析",
label="選擇分析模式",
info="""
• 單張分析:分析單張圖片(如上傳多張僅分析第一張)
• 比較分析:比較多張圖片的差異和相似點(推薦)
• 批量分析:對每張圖片進行單獨分析
"""
)
gr.Markdown("### ✏️ 分析設定")
prompt_input = gr.Textbox(
label="自訂提示詞 (可選)",
placeholder="留空將使用智能預設提示詞...",
lines=3,
info="不同分析模式會自動使用相應的最佳化提示詞"
)
gr.Markdown("### 🔑 Gemini API Key")
gemini_key = gr.Textbox(
label="Gemini API Key",
placeholder="AIza...",
type="password"
)
with gr.Column(scale=1):
gr.HTML("""
👥 多客戶專屬API配置
配置格式:客戶名稱|收件人郵箱|Resend API Key
每行一個客戶,每個客戶使用專屬的API Key
🔑 專屬版本:每個客戶獨立API管理,費用分離!
""")
client_configs = gr.Textbox(
label="🏢 客戶專屬API配置列表",
placeholder="""客戶A|clientA@example.com|re_xxxxxxxxx_A
客戶B|clientB@example.com|re_xxxxxxxxx_B
客戶C|clientC@example.com|re_xxxxxxxxx_C
# 這是註釋行,會被忽略
客戶D|clientD@example.com|re_xxxxxxxxx_D""",
lines=10,
info="每行一個客戶,格式:客戶名稱|郵箱|Resend API Key。支援 # 開頭的註釋行"
)
with gr.Accordion("如何獲取 API Keys", open=False):
gr.Markdown("""
**Gemini API Key:**
1. 前往 [Google AI Studio](https://aistudio.google.com/app/apikey)
2. 創建新的 API Key
3. 複製 API Key(格式:AIza...)
**Resend API Key (每個客戶專屬):**
1. 前往 [Resend](https://resend.com/api-keys)
2. 為每個客戶註冊獨立帳號或創建專屬 API Key
3. 複製各自的 API Key(格式:re_...)
4. 每個客戶的使用量和費用完全獨立
**專屬API配置格式:**
```
客戶名稱|client@email.com|re_客戶專屬API金鑰
公司A|companyA@domain.com|re_ABC123_companyA
團隊B|teamB@company.org|re_DEF456_teamB
```
**專屬版本優勢:**
- 🔐 每個客戶的API Key完全獨立
- 💰 使用量和費用分離,便於管理
- 📊 可以追蹤每個客戶的發送狀況
- 🛡️ 更高的安全性和隱私保護
- 🎯 客戶可以自行控制發送配額
**注意事項:**
- 確保每個API Key格式正確(以re_開頭)
- 建議客戶自行管理API Key和配額
- 測試時請確認所有API Key都有效
- 一次最多建議配置 20 個客戶
""")
gr.Markdown("### 🚀 執行操作")
analyze_btn = gr.Button(
"🔍 開始AI分析並發送給所有客戶",
variant="primary",
size="lg"
)
gr.Markdown("### 📊 處理結果")
with gr.Row():
status_output = gr.Textbox(
label="📈 處理狀態與發送統計",
lines=8,
interactive=False
)
with gr.Row():
with gr.Column():
analysis_output = gr.Textbox(
label="🤖 AI分析結果",
lines=15,
interactive=False
)
with gr.Column():
email_output = gr.Textbox(
label="📧 多客戶專屬API郵件發送結果",
lines=15,
interactive=False
)
with gr.Row():
download_btn = gr.Button("💾 下載完整CSV報告", variant="secondary")
csv_file = gr.File(label="CSV檔案", visible=False)
# 事件綁定
def update_gallery(files):
if files:
return [file.name for file in files]
return []
images_input.change(
fn=update_gallery,
inputs=[images_input],
outputs=[images_gallery]
)
analyze_btn.click(
fn=analyze_images_and_send_emails,
inputs=[images_input, analysis_mode, prompt_input, client_configs, gemini_key],
outputs=[status_output, analysis_output, email_output]
)
def download_csv(images, analysis_mode, custom_prompt, analysis_result, client_configs):
if analysis_result and not analysis_result.startswith("❌"):
filename = save_results_to_csv(images, analysis_mode, custom_prompt, analysis_result, client_configs)
if not filename.startswith("儲存失敗"):
return gr.update(value=filename, visible=True)
return gr.update(visible=False)
download_btn.click(
fn=download_csv,
inputs=[images_input, analysis_mode, prompt_input, analysis_output, client_configs],
outputs=csv_file
)
# 使用說明
with gr.Accordion("📝 專屬API系統使用說明", open=False):
gr.Markdown("""
### 🏢 專屬API客戶配置格式
**基本格式:**
```
客戶名稱|收件人郵箱|Resend API Key
```
**配置範例:**
```
科技公司A|tech@companyA.com|re_ABC123_techA
設計工作室B|design@studioB.net|re_DEF456_designB
行銷團隊C|marketing@teamC.org|re_GHI789_marketC
# 這是註釋,可以用來分組或說明
個人客戶D|personal@clientD.com|re_JKL012_personalD
```
### 🔑 專屬API版本特色
**核心優勢:**
- ✅ 每個客戶使用專屬的Resend API Key
- ✅ 使用量和費用完全獨立,便於管理
- ✅ 提供更高的安全性和隱私保護
- ✅ 可以追蹤每個客戶的發送狀況
- ✅ 支援客戶自主控制發送配額
- ✅ 個性化郵件標示API來源
**vs 統一API版本差異:**
| 功能 | 統一API版本 | 專屬API版本 |
|------|-------------|-------------|
| API Key數量 | 1個共用 | 每客戶1個 |
| 費用管理 | 統一計費 | 獨立計費 |
| 安全性 | 一般 | 更高 |
| 配額控制 | 統一控制 | 客戶自控 |
| 追蹤能力 | 基本 | 詳細 |
### 👥 客戶管理功能
**支援特性:**
- ✅ 多客戶同時發送(建議1-20個客戶)
- ✅ 專屬 API Key 管理,安全性更高
- ✅ 個性化郵件內容(包含客戶名稱和API資訊)
- ✅ 發送狀態統計和詳細報告
- ✅ 註釋行支援(# 開頭)
- ✅ API Key 驗證和格式檢查
**配置規則:**
- 每行一個客戶配置
- 使用 `|` 分隔三個欄位
- 客戶名稱不可重複
- 郵箱必須是有效格式
- Resend API Key 必須以 `re_` 開頭
- 每個API Key必須有效且有足夠配額
### 📧 專屬API郵件發送流程
**1. 配置驗證階段**
- 驗證客戶配置格式正確性
- 檢查API Key格式(必須以re_開頭)
- 驗證郵箱地址格式
- 確認客戶名稱唯一性
**2. 圖片分析階段**
- 上傳圖片並選擇分析模式
- 使用Gemini AI 進行圖片內容分析
- 生成統一的分析報告
**3. 專屬API發送階段**
- 為每個客戶設定專屬的API Key
- 使用對應的API Key發送郵件
- 在郵件中標示使用的API Key資訊
- 記錄每個客戶的發送結果
**4. 結果統計與追蹤**
- 顯示每個客戶的發送狀態
- 標示使用的API Key(前8碼)
- 統計總成功/失敗數量
- 提供詳細的錯誤資訊
### ⚡ 效能與限制
**建議使用量:**
- **客戶數量**:1-20個客戶為最佳
- **圖片數量**:2-10張圖片
- **圖片大小**:單張不超過 10MB
- **處理時間**:隨客戶數量線性增加
**API 配額考量:**
- **Gemini API**:一次分析消耗一次配額
- **Resend API**:每個客戶使用專屬配額
- **獨立計費**:每個客戶的費用完全分離
- **配額管理**:客戶可自行監控和控制
**專屬版本優勢:**
- 🔐 **更高安全性**:API Key完全隔離
- 💰 **費用透明**:每個客戶獨立計費
- 📊 **精確追蹤**:可追蹤每個API的使用狀況
- 🎯 **自主控制**:客戶可控制發送配額
- 🛡️ **隱私保護**:客戶間資訊完全隔離
### 🛠️ 故障排除
**常見錯誤:**
- **配置格式錯誤**:檢查 `|` 分隔符數量(應為2個)
- **API Key 格式錯誤**:確認以 `re_` 開頭
- **API Key 無效**:檢查每個客戶的API Key有效性
- **郵箱格式錯誤**:確保包含 @ 和有效域名
- **重複客戶名稱**:每個客戶名稱必須唯一
- **配額不足**:檢查特定客戶的API配額
**專屬版除錯建議:**
- 先用 1 個客戶測試配置
- 逐一驗證每個API Key的有效性
- 確認每個API Key都有足夠配額
- 檢查客戶端的API Key權限設定
- 查看具體的API Key錯誤訊息
- 建議客戶監控自己的API使用量
### 💡 最佳實踐
**專屬API配置管理:**
- 要求客戶自行註冊Resend帳號
- 建立標準化的API Key命名規範
- 定期檢查各客戶的API Key狀態
- 建議客戶設定使用量警告
**發送策略:**
- 測試時先用1個客戶驗證配置
- 確認每個API Key都有足夠配額
- 建議客戶分散API使用時間
- 提供API使用量監控建議
**安全考量:**
- 提醒客戶妥善保管API Key
- 建議定期輪換API Key
- 不在日誌中記錄完整API Key
- 建議客戶監控異常使用
### 🔄 版本比較
**專屬API版本 vs 統一API版本:**
| 特性 | 專屬API版本 | 統一API版本 |
|------|-------------|-------------|
| **安全性** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| **配置複雜度** | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| **費用管理** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| **追蹤能力** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| **客戶自主性** | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| **部署簡易度** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
**適用場景:**
- **專屬API版本**:企業客戶、長期合作、高安全要求
- **統一API版本**:快速部署、測試環境、小型客戶
### 📋 配置檢查清單
**部署前檢查:**
- [ ] 每個客戶都有有效的Resend API Key
- [ ] 所有API Key都以 `re_` 開頭
- [ ] 客戶名稱沒有重複
- [ ] 郵箱地址格式正確
- [ ] Gemini API Key有效且有足夠配額
- [ ] 測試環境中先驗證少數客戶
**發送前檢查:**
- [ ] 確認所有API Key都有足夠發送配額
- [ ] 圖片格式和大小符合要求
- [ ] 選擇適當的分析模式
- [ ] 預覽客戶配置列表正確
- [ ] 備份重要的配置資訊
""")
# 提示詞範例
with gr.Accordion("🎯 提示詞範例", open=False):
gr.Markdown("### 📸 單張分析提示詞")
gr.Examples(
examples=[
["請詳細描述這張圖片,包括主要物件、顏色、構圖和可能的背景故事"],
["提取並分析圖片中的所有文字內容,並解釋其含義"],
["分析圖片的藝術風格、攝影技法和視覺效果"],
["識別圖片中的品牌、標誌和商業元素"],
["描述圖片中人物的情緒、動作和互動關係"]
],
inputs=prompt_input,
label="點擊使用單張分析範例"
)
gr.Markdown("### 🔄 比較分析提示詞")
gr.Examples(
examples=[
["比較這些圖片的相似點和差異,分析它們的關聯性"],
["分析這些圖片在構圖、色彩和風格上的異同"],
["比較圖片中產品或物件的特徵差異"],
["分析這些圖片的時間順序和變化過程"],
["比較不同角度或場景下同一主題的表現差異"]
],
inputs=prompt_input,
label="點擊使用比較分析範例"
)
# 客戶配置範例
with gr.Accordion("🏢 專屬API客戶配置範例", open=False):
gr.Markdown("### 配置範例")
gr.Examples(
examples=[
["""科技公司A|tech@companyA.com|re_ABC123_techA
設計工作室B|design@studioB.net|re_DEF456_designB
行銷團隊C|marketing@teamC.org|re_GHI789_marketC"""],
["""# 企業客戶群組
大企業甲|corp@bigcompany.com|re_CORP001_enterprise
中小企業乙|info@smallbiz.net|re_SME002_business
# 個人客戶群組
個人客戶A|john@gmail.com|re_PERSONAL003_john
個人客戶B|mary@yahoo.com|re_PERSONAL004_mary"""],
["""測試客戶1|test1@example.com|re_TEST001_client1
測試客戶2|test2@example.com|re_TEST002_client2"""]
],
inputs=client_configs,
label="點擊使用專屬API配置範例"
)
# 版本資訊
gr.HTML("""
🚀 Powered by Google Gemini 2.0 & Resend
📍 Deployed on Hugging Face Spaces
🔥 專屬API Key版本 4.0 | Made with ❤️ using Gradio
🔑 每客戶專屬API管理 | ⭐ 支援最多10張圖片同時分析比較
📧 新功能:客戶專屬API Key批量郵件發送系統
🎯 v4.0 特色:獨立API管理,更高安全性,費用透明化
💰 專屬版優勢:獨立計費 | 🔐 安全隔離 | 📊 精確追蹤
""")
return demo
# 主程式入口
if __name__ == "__main__":
# 建立並啟動介面
demo = create_interface()
# Hugging Face Spaces 部署設定
demo.launch(
share=False,
show_error=True,
show_api=False,
quiet=False
)