study / services /image_model_service.py
xiaolongmr
1.07
59af925
Raw History Blame Contribute Delete
3.59 kB
"""生图可用模型的判定规则(与「对话可用模型」对称)。
``/api/image/models`` 给出**全部能生图的模型**:账号池上游内置生图模型
(``gpt-image-2`` 及其 codex 变体)+ 第三方接入的生图模型。
候选判据复用 services/chat_model_service.py 的 ``supports_image_generation``:
优先看第三方的能力字段(``txt2img`` / ``img2img``),没有该字段的上游模型退回名字判定。
多模态模型(能力里同时有 ``chat`` 与 ``txt2img``)会同时出现在对话与生图两个列表里。
**默认全部启用。** 第三方生图模型能不能用,本来就由第三方生图配置(分组 / 模型开关、
计费、路由)决定;这里的开关只是**展示层过滤**,只影响模型是否出现在生图下拉里,
不改变计费、路由、额度与对外 API 的行为。所以升级后不会莫名其妙少模型,
管理员可以按需勾掉不想在列表里看到的。
"""
from __future__ import annotations
from typing import Any
from services.chat_model_service import (
SOURCE_THIRD_PARTY,
SOURCE_UPSTREAM,
_clean,
image_capabilities,
model_source,
supports_image_generation,
)
# 生图列表里的来源标签:上游内置生图模型 / 第三方接入生图模型。
IMAGE_SOURCE_BUILTIN = "builtin"
IMAGE_SOURCE_THIRD_PARTY = "third_party"
def image_model_source(item: dict[str, Any]) -> str:
"""生图模型的来源:``builtin`` = 账号池上游内置,``third_party`` = 第三方接入。"""
if model_source(item) == SOURCE_THIRD_PARTY:
return IMAGE_SOURCE_THIRD_PARTY
return IMAGE_SOURCE_BUILTIN
def _clean_id_set(value: object) -> set[str]:
if not isinstance(value, list):
return set()
return {_clean(item) for item in value if _clean(item)}
def resolve_image_models(
items: list[Any],
overrides: dict[str, Any] | None = None,
) -> list[dict[str, Any]]:
"""筛出能生图的模型,并标注 ``image_enabled`` / ``image_default_enabled``。
只保留 ``supports_image_generation`` 为真的条目(对话模型不会混进来);
分不清能不能生图的模型一律不放进候选,避免生图下拉里出现选不了的模型。
"""
source = overrides if isinstance(overrides, dict) else {}
include = _clean_id_set(source.get("include"))
exclude = _clean_id_set(source.get("exclude"))
resolved: list[dict[str, Any]] = []
for item in items or []:
if not isinstance(item, dict):
continue
model_id = _clean(item.get("id"))
if not model_id or not supports_image_generation(item):
continue
if model_id in include:
enabled = True
elif model_id in exclude:
enabled = False
else:
enabled = True
resolved.append({
**item,
"image_enabled": enabled,
"image_default_enabled": True,
"image_source": image_model_source(item),
"image_capabilities": sorted(image_capabilities(item)),
})
# 已启用的排前面;同组内上游内置模型优先,再按模型名排序。
resolved.sort(key=lambda entry: (
0 if entry["image_enabled"] else 1,
0 if entry["image_source"] == IMAGE_SOURCE_BUILTIN else 1,
str(entry.get("id") or ""),
))
return resolved
__all__ = [
"IMAGE_SOURCE_BUILTIN",
"IMAGE_SOURCE_THIRD_PARTY",
"image_model_source",
"resolve_image_models",
"SOURCE_THIRD_PARTY",
"SOURCE_UPSTREAM",
]