CalorieApp / app.py
huchiahsi's picture
修復 Part.from_text() API 使用錯誤
d40bc97
import os
import gradio as gr
from google import genai
from google.genai import types
from PIL import Image
import io
import base64
# 載入環境變數(本機開發時需要)
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
# 配置Google AI
def configure_google_ai():
"""配置Google AI API"""
api_key = os.getenv("GOOGLE_API_KEY")
if not api_key:
raise ValueError("請設定GOOGLE_API_KEY環境變數")
# 使用新的 Gen AI 客戶端
client = genai.Client(api_key=api_key)
return client
# 初始化模型
try:
client = configure_google_ai()
model_name = "gemini-1.5-flash"
except Exception as e:
print(f"警告:無法初始化Google AI模型 - {e}")
client = None
def analyze_food_calories(image):
"""
分析圖片中的食物並估算卡路里
Args:
image: PIL Image 物件
Returns:
str: 分析結果
"""
if client is None:
return "錯誤:Google AI模型未正確初始化,請檢查API KEY設定"
try:
# 將圖片轉換為 base64
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
img_base64 = base64.b64encode(img_byte_arr).decode('utf-8')
# 準備提示詞
prompt = """
請分析這張圖片中的內容:
1. 首先判斷圖片中是否包含食物
2. 如果不是食物,請回答:「這個不是食物」
3. 如果是食物,請:
- 識別食物種類
- 估算大概的份量
- 計算大概的卡路里含量
- 以繁體中文回答
請以以下格式回答:
- 食物名稱:[食物名稱]
- 估算份量:[份量描述]
- 預估卡路里:[卡路里數值] 大卡
- 營養說明:[簡短的營養價值說明]
如果不是食物,就直接回答「這個不是食物」。
"""
# 建立內容,包含文字和圖片
contents = [
types.Content(
role="user",
parts=[
types.Part.from_text(text=prompt),
types.Part.from_bytes(
data=img_byte_arr,
mime_type="image/png"
)
]
)
]
# 生成回應
response = client.models.generate_content(
model=model_name,
contents=contents,
config=types.GenerateContentConfig(
temperature=0.4,
max_output_tokens=1024,
)
)
if response.text:
return response.text
else:
return "無法生成回應"
except Exception as e:
return f"分析時發生錯誤:{str(e)}"
def process_image(image):
"""
處理上傳的圖片
Args:
image: Gradio上傳的圖片
Returns:
str: 分析結果
"""
if image is None:
return "請上傳一張圖片"
try:
# 確保圖片是PIL Image格式
if isinstance(image, str):
# 如果是路徑字串,載入圖片
pil_image = Image.open(image)
else:
pil_image = image
# 分析圖片
result = analyze_food_calories(pil_image)
return result
except Exception as e:
return f"處理圖片時發生錯誤:{str(e)}"
# 建立Gradio介面
def create_interface():
"""建立Gradio使用者介面"""
# 自訂CSS樣式
css = """
.gradio-container {
font-family: 'Microsoft JhengHei', sans-serif;
}
.title {
text-align: center;
color: #2E7D32;
margin-bottom: 20px;
}
.description {
text-align: center;
color: #666;
margin-bottom: 30px;
}
"""
with gr.Blocks(css=css, title="食物卡路里檢測器") as demo:
gr.HTML("<h1 class='title'>🍎 食物卡路里檢測器</h1>")
gr.HTML("<p class='description'>上傳食物照片,AI會幫你識別食物種類並估算卡路里含量</p>")
with gr.Row():
with gr.Column():
# 圖片上傳元件
image_input = gr.Image(
label="上傳食物照片",
type="pil",
height=400
)
# 分析按鈕
analyze_btn = gr.Button(
"🔍 分析卡路里",
variant="primary",
size="lg"
)
with gr.Column():
# 結果顯示
result_output = gr.Textbox(
label="分析結果",
lines=10,
placeholder="上傳圖片後點擊分析按鈕...",
interactive=False
)
# 使用說明
gr.HTML("""
<div style="margin-top: 30px; padding: 20px; background-color: #f5f5f5; border-radius: 10px;">
<h3>📋 使用說明:</h3>
<ul>
<li>📸 上傳一張包含食物的清晰照片</li>
<li>🤖 AI會自動識別食物種類</li>
<li>📊 獲得卡路里估算和營養資訊</li>
<li>⚠️ 如果不是食物,系統會提醒您</li>
</ul>
<p><strong>注意:</strong>卡路里估算僅供參考,實際數值可能因烹飪方式和份量而有所差異。</p>
</div>
""")
# 設定事件處理
analyze_btn.click(
fn=process_image,
inputs=[image_input],
outputs=[result_output]
)
# 也可以在上傳圖片後自動分析
image_input.change(
fn=process_image,
inputs=[image_input],
outputs=[result_output]
)
return demo
# 主程式
if __name__ == "__main__":
# 建立介面
demo = create_interface()
# 啟動應用
# HuggingFace Spaces 使用預設設定
demo.launch()