feat(网关): 接口4 改由网关本机直接调豆包视觉模型,不再代理到 worker
- gateway/app.py: 接口4 handler 改为直接调用 face_features 模块 - face_features.py: API Key 读取支持 gateway/config.json - gateway/config.example.json: 增加 ark_api_key 配置项
This commit is contained in:
+68
-7
@@ -5,11 +5,17 @@
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from fastapi import FastAPI, Request
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, File, Form, Request, UploadFile
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from gateway.config import load_config
|
||||
@@ -217,9 +223,6 @@ _GROW_B_FORMS = {
|
||||
"marked_image_file": {"type": "file", "description": "划线图片文件"},
|
||||
"marked_image_url": {"type": "string", "description": "划线图片 URL"},
|
||||
"marked_image_base64": {"type": "string", "description": "划线图片 base64"},
|
||||
"original_image_file": {"type": "file", "description": "原始用户照片文件"},
|
||||
"original_image_url": {"type": "string", "description": "原始用户照片 URL"},
|
||||
"original_image_base64": {"type": "string", "description": "原始用户照片 base64"},
|
||||
}
|
||||
|
||||
|
||||
@@ -242,9 +245,67 @@ async def hair_grow_b(request: Request):
|
||||
|
||||
|
||||
@app.post("/api/v1/face/features", tags=["人脸分析"])
|
||||
async def face_features(request: Request):
|
||||
"""接口4:用户特征分析"""
|
||||
return await _proxy(request, "/api/v1/face/features")
|
||||
async def face_features(
|
||||
image_file: Optional[UploadFile] = File(default=None, description="上传图片文件(JPG/PNG,≤ 1 MB)"),
|
||||
image_url: Optional[str] = Form(default=None, description="图片 URL"),
|
||||
image_base64: Optional[str] = Form(default=None, description="图片 base64(需带前缀)"),
|
||||
):
|
||||
"""接口4:用户特征分析 — 本机直接调豆包视觉模型,不经过 worker。"""
|
||||
import uuid as _uuid
|
||||
|
||||
# 三选一校验
|
||||
provided = [x for x in (image_file, image_url, image_base64) if x]
|
||||
if len(provided) != 1:
|
||||
return JSONResponse(status_code=400, content={
|
||||
"code": 1007, "message": "图片参数错误:必须且只能传 image_file / image_url / image_base64 其中一个",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
|
||||
img_bytes = None
|
||||
if image_file:
|
||||
raw = await image_file.read()
|
||||
if len(raw) > 1_000_000:
|
||||
return JSONResponse(status_code=400, content={
|
||||
"code": 1006, "message": "文件超出 1 MB 限制",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
img_bytes = raw
|
||||
elif image_base64:
|
||||
b64 = image_base64
|
||||
if "," in b64:
|
||||
b64 = b64.split(",", 1)[1]
|
||||
try:
|
||||
img_bytes = base64.b64decode(b64)
|
||||
except Exception:
|
||||
return JSONResponse(status_code=400, content={
|
||||
"code": 1008, "message": "图片格式不支持(base64 解码失败)",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from face_features import analyze_features, has_face
|
||||
|
||||
try:
|
||||
feats = await run_in_threadpool(analyze_features, img_bytes, image_url)
|
||||
except Exception as ex:
|
||||
logger.exception("接口4 豆包调用失败")
|
||||
return JSONResponse(status_code=503, content={
|
||||
"code": 1007, "message": f"分析服务异常:{ex}",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
|
||||
if not has_face(feats):
|
||||
return JSONResponse(status_code=400, content={
|
||||
"code": 1001, "message": "无法识别人像",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
|
||||
return JSONResponse(status_code=200, content={
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"request_id": f"gw-{_uuid.uuid4().hex[:8]}",
|
||||
"data": {"features": json.dumps(feats, ensure_ascii=False)},
|
||||
})
|
||||
|
||||
|
||||
@app.post("/api/v1/hairline/generate", tags=["人脸分析"])
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"unhealthy_threshold": 2,
|
||||
"healthy_threshold": 1
|
||||
},
|
||||
"ark_api_key": "",
|
||||
"dispatch": {
|
||||
"per_worker_concurrency": 1,
|
||||
"queue_wait_seconds": 30,
|
||||
|
||||
Reference in New Issue
Block a user