Spaces:
Runtime error
Runtime error
File size: 5,980 Bytes
173561a a499cd3 173561a a499cd3 173561a a499cd3 173561a a499cd3 173561a 8799348 a499cd3 8799348 173561a 8799348 f19800f 8799348 173561a 8799348 173561a 8799348 a499cd3 8799348 a499cd3 8799348 85a6c18 a499cd3 8799348 173561a a499cd3 | 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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | import os
import json
import base64
import logging
from datetime import datetime
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional
import gradio as gr
# 載入自訂的生圖與後製模組
from image_generator import generate_good_morning_image
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
GEMINI_API_KEY = os.environ.get("GOOGLE_API_KEY")
HF_TOKEN = os.environ.get("HF_TOKEN")
app = FastAPI(title="長輩圖產生器整合版")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
DATA_DIR = os.path.abspath("data")
STATIC_DIR = os.path.abspath("static")
HISTORY_FILE = os.path.join(DATA_DIR, "history.json")
os.makedirs(DATA_DIR, exist_ok=True)
os.makedirs(STATIC_DIR, exist_ok=True)
def read_history():
if not os.path.exists(HISTORY_FILE):
return []
try:
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
logger.error(f"讀取歷史紀錄時發生錯誤: {e}")
return []
def write_history(history_data):
try:
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
json.dump(history_data, f, ensure_ascii=False, indent=2)
except Exception as e:
logger.error(f"寫入歷史紀錄時發生錯誤: {e}")
# --- [1. 原本的 FastAPI API 功能保留] ---
class GenerateRequest(BaseModel):
message: str
custom_greeting: Optional[str] = None
@app.post("/api/generate")
async def generate_endpoint(payload: GenerateRequest):
logger.info(f"收到生圖命令請求: {payload.message}")
# 直接呼叫,生圖模組會自動去抓你設定在 Hugging Face Secrets 裡的安全金鑰
result = generate_good_morning_image(
user_input=payload.message,
custom_greeting=payload.custom_greeting
)
if not result.get("success"):
raise HTTPException(status_code=500, detail=result.get("error", "早安圖流水線運行崩潰"))
image_path = result["image_path"]
try:
with open(image_path, "rb") as img_file:
base64_data = base64.b64encode(img_file.read()).decode("utf-8")
base64_uri = f"data:image/jpeg;base64,{base64_data}"
except Exception as e:
logger.error(f"圖檔轉碼為 Base64 時發生錯誤: {e}")
base64_uri = ""
history = read_history()
new_entry = {
"id": result["id"],
"query": result["query"],
"greeting_text": result["greeting_text"],
"expanded_prompt": result["expanded_prompt"],
"filename": result["filename"],
"created_at": datetime.now().isoformat()
}
history.insert(0, new_entry)
write_history(history)
return {
"success": True,
"id": result["id"],
"query": result["query"],
"greeting_text": result["greeting_text"],
"expanded_prompt": result["expanded_prompt"],
"image_url": f"/api/image/{result['id']}",
"image_base64": base64_uri
}
@app.get("/api/latest")
async def get_latest_image():
history = read_history()
if not history:
raise HTTPException(status_code=404, detail="目前歷史資料庫為空,請先生成一張圖片。")
latest = history[0]
image_path = os.path.join(DATA_DIR, latest["filename"])
if not os.path.exists(image_path):
raise HTTPException(status_code=404, detail="圖片成品檔案已不存在。")
return FileResponse(image_path, media_type="image/jpeg", filename=latest["filename"])
@app.get("/api/image/{image_id}")
async def get_image_by_id(image_id: str):
image_path = os.path.join(DATA_DIR, f"{image_id}.jpg")
if not os.path.exists(image_path):
raise HTTPException(status_code=404, detail="找不到指定 ID 的圖片成品")
return FileResponse(image_path, media_type="image/jpeg", filename=f"{image_id}.jpg")
@app.get("/api/history")
async def get_history():
return read_history()
# --- [2. 恢復:原本的自訂網頁首頁與靜態檔案夾掛載] ---
@app.get("/")
async def root():
index_path = os.path.join(STATIC_DIR, "index.html")
if os.path.exists(index_path):
return FileResponse(index_path)
return {"message": "伺服器成功啟動!請將 index.html 放入 static 目錄下以開啟模擬器介面。"}
# 掛載 static 靜態檔案夾,讓 index.html 可以順利讀取 style.css 與 app.js
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
# --- [3. Gradio 後台測試介面 - 改掛載到 /gradio] ---
def gradio_test_interface(user_query):
if not user_query:
return None, "請輸入主題"
result = generate_good_morning_image(user_input=user_query)
if result["success"]:
return result["image_path"], result["greeting_text"]
else:
return None, f"生成失敗: {result.get('error')}"
demo = gr.Interface(
fn=gradio_test_interface,
inputs=gr.Textbox(label="輸入圖片主題 (例如:貓咪、蓮花)", placeholder="想看什麼主題的長輩圖?"),
outputs=[
gr.Image(label="生成的早安圖成品"),
gr.Textbox(label="生成的賀詞")
],
title="🌸 超俗早安長輩圖產生器 (後台測試版) 🌸",
description="這是獨立的測試專區。若要造訪原本跑的模擬器,請直接前往主網頁路徑。",
flagging_mode="never"
)
# 關鍵:將 path 設定為 "/gradio"
app = gr.mount_gradio_app(app, demo, path="/gradio")
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", 7860))
uvicorn.run(app, host="0.0.0.0", port=port) |