feat(ai): enforce direct image edit contract
This commit is contained in:
+52
-2
@@ -142,10 +142,10 @@ DEFAULT_AI_MODELS_CONFIG = {
|
||||
"name": "Nano Banana 2",
|
||||
"category": "image",
|
||||
"enabled": True,
|
||||
"url": "https://api.vectorengine.ai/v1/chat/completions",
|
||||
"url": "https://api.vectorengine.ai/v1",
|
||||
"model": "gemini-3.1-flash-image-preview",
|
||||
"api_key": "",
|
||||
"api_type": "auto",
|
||||
"api_type": "images_edits",
|
||||
"connect_timeout_seconds": 30,
|
||||
"timeout_seconds": 0,
|
||||
"extra_body": {},
|
||||
@@ -1018,6 +1018,56 @@ def get_model(name, path=AI_MODELS_PATH) -> dict:
|
||||
return copy.deepcopy(models[_model_index(models, name)])
|
||||
|
||||
|
||||
def is_image_edit_model(model) -> bool:
|
||||
"""Return whether a model satisfies the direct image-edit contract."""
|
||||
|
||||
return (
|
||||
isinstance(model, dict)
|
||||
and model.get("category") == "image"
|
||||
and model.get("api_type") == "images_edits"
|
||||
)
|
||||
|
||||
|
||||
def image_model_config_error(model) -> str:
|
||||
"""Return a Chinese actionable error for a direct image model, if any."""
|
||||
|
||||
if not isinstance(model, dict) or model.get("category") != "image":
|
||||
return "当前模型不是图片模型"
|
||||
if model.get("api_type") != "images_edits":
|
||||
return "图片模型仅支持 OpenAI 图片编辑接口,请在设置中选择该接口类型"
|
||||
missing = [
|
||||
field
|
||||
for field in ("url", "model", "api_key")
|
||||
if not str(model.get(field, "") or "").strip()
|
||||
]
|
||||
if missing:
|
||||
return "图片模型缺少必要配置:" + "、".join(missing)
|
||||
url = str(model.get("url") or "").strip()
|
||||
parts = urllib.parse.urlsplit(url)
|
||||
if parts.scheme not in {"http", "https"} or not parts.netloc:
|
||||
return "图片模型网址必须使用 http 或 https"
|
||||
try:
|
||||
connect_timeout = int(model.get("connect_timeout_seconds", 0) or 0)
|
||||
except (TypeError, ValueError):
|
||||
connect_timeout = 0
|
||||
if connect_timeout <= 0:
|
||||
return "图片模型连接超时必须大于 0 秒"
|
||||
return ""
|
||||
|
||||
|
||||
def check_image_model_config(name, path=AI_MODELS_PATH) -> dict:
|
||||
"""Validate one image model locally without making a billable request."""
|
||||
|
||||
try:
|
||||
model = get_model(name, path=path)
|
||||
error = image_model_config_error(model)
|
||||
if error:
|
||||
return {"ok": False, "check_only": True, "error": error}
|
||||
return {"ok": True, "check_only": True}
|
||||
except Exception as exc:
|
||||
return {"ok": False, "check_only": True, "error": str(exc)}
|
||||
|
||||
|
||||
|
||||
def model_request_url(model) -> str:
|
||||
"""Return the HTTP endpoint used for a configured AI model."""
|
||||
|
||||
Reference in New Issue
Block a user