Spaces:
Sleeping
Sleeping
feat: improve demo upload flow and model selection
Browse files新增 demo 頁面的模型切換功能,支援在同一張圖片上切換不同模型重新推論,
並調整預覽圖片的縮放與顯示尺寸,避免被外框裁切。
改寫 multipart 表單解析流程,支援重用既有預覽圖並放寬上傳大小限制,
同時修正手動解析表單時無法正確辨識上傳檔案的問題。
app.py
CHANGED
|
@@ -8,6 +8,7 @@ from fastapi import FastAPI, HTTPException, Request, UploadFile
|
|
| 8 |
from fastapi.responses import HTMLResponse
|
| 9 |
from fastapi.templating import Jinja2Templates
|
| 10 |
from PIL import Image, UnidentifiedImageError
|
|
|
|
| 11 |
|
| 12 |
from model_service import MODEL_CONFIGS, get_model_config, get_model_service
|
| 13 |
|
|
@@ -116,6 +117,12 @@ async def _predict_upload(
|
|
| 116 |
return result, data
|
| 117 |
|
| 118 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
async def _parse_demo_form(request: Request) -> tuple[UploadFile | None, str, str | None]:
|
| 120 |
try:
|
| 121 |
form = await request.form(max_part_size=MAX_UPLOAD_SIZE)
|
|
@@ -124,8 +131,7 @@ async def _parse_demo_form(request: Request) -> tuple[UploadFile | None, str, st
|
|
| 124 |
except Exception as exc:
|
| 125 |
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
| 126 |
|
| 127 |
-
|
| 128 |
-
file = file_value if isinstance(file_value, UploadFile) else None
|
| 129 |
model_name = str(form.get("model_name") or ACTIVE_MODEL_CONFIG.name)
|
| 130 |
existing_image_data_url = form.get("existing_image_data_url")
|
| 131 |
if existing_image_data_url is not None:
|
|
@@ -141,8 +147,7 @@ async def _parse_predict_form(request: Request) -> tuple[UploadFile | None, str]
|
|
| 141 |
except Exception as exc:
|
| 142 |
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
| 143 |
|
| 144 |
-
|
| 145 |
-
file = file_value if isinstance(file_value, UploadFile) else None
|
| 146 |
model_name = str(form.get("model_name") or ACTIVE_MODEL_CONFIG.name)
|
| 147 |
return file, model_name
|
| 148 |
|
|
|
|
| 8 |
from fastapi.responses import HTMLResponse
|
| 9 |
from fastapi.templating import Jinja2Templates
|
| 10 |
from PIL import Image, UnidentifiedImageError
|
| 11 |
+
from starlette.datastructures import UploadFile as StarletteUploadFile
|
| 12 |
|
| 13 |
from model_service import MODEL_CONFIGS, get_model_config, get_model_service
|
| 14 |
|
|
|
|
| 117 |
return result, data
|
| 118 |
|
| 119 |
|
| 120 |
+
def _coerce_upload_file(value: object) -> UploadFile | None:
|
| 121 |
+
if isinstance(value, (UploadFile, StarletteUploadFile)):
|
| 122 |
+
return value
|
| 123 |
+
return None
|
| 124 |
+
|
| 125 |
+
|
| 126 |
async def _parse_demo_form(request: Request) -> tuple[UploadFile | None, str, str | None]:
|
| 127 |
try:
|
| 128 |
form = await request.form(max_part_size=MAX_UPLOAD_SIZE)
|
|
|
|
| 131 |
except Exception as exc:
|
| 132 |
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
| 133 |
|
| 134 |
+
file = _coerce_upload_file(form.get("file"))
|
|
|
|
| 135 |
model_name = str(form.get("model_name") or ACTIVE_MODEL_CONFIG.name)
|
| 136 |
existing_image_data_url = form.get("existing_image_data_url")
|
| 137 |
if existing_image_data_url is not None:
|
|
|
|
| 147 |
except Exception as exc:
|
| 148 |
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
| 149 |
|
| 150 |
+
file = _coerce_upload_file(form.get("file"))
|
|
|
|
| 151 |
model_name = str(form.get("model_name") or ACTIVE_MODEL_CONFIG.name)
|
| 152 |
return file, model_name
|
| 153 |
|