Files
MemeMeow/backend/visual_models.py
infstellar 6d7312a627 feat(config): centralize database visual and agent runtime settings
Expose validated database, visual model, reverse-image, executor, and runtime settings with secure token-file loading.

集中管理数据库、视觉模型、反向搜图、executor 和运行时配置,并安全读取 token 文件。
2026-08-15 15:21:14 +08:00

143 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""视觉模型清单与持久化迁移边界。
该模块位于视觉服务和主后端配置之间,集中声明官方模型的维度、源码提交、
checkpoint 文件名以及预处理身份。当前活动空间固定为 DINOv2 ViT-B/14;
历史 DINOv3 空间仍保留清单,只有在对应的独立 Alembic 迁移完成后才能启用。
"""
from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
DINOV2_SOURCE_COMMIT = "7764ea0f912e53c92e82eb78a2a1631e92725fc8"
DINOV3_SOURCE_COMMIT = "6876159a11b4df116f30f667f8c9888617df0751"
ACTIVE_VISUAL_MODEL_ID = "dinov2_vitb14"
ACTIVE_VISUAL_SCHEMA_REVISION = "0009_dinov2_vitb14_visual_search"
@dataclass(frozen=True)
class VisualModelSpec:
"""一个官方视觉模型空间的静态身份和部署来源。"""
model: str
dimensions: int
preprocess_version: str
source_commit: str
source_package: str
source_files: tuple[str, ...]
backbone_name: str
checkpoint_filename: str
checkpoint_url: str
schema_revision: str
runtime_supported: bool = False
@property
def source_marker_filename(self) -> str:
"""返回源码目录中用于防止版本漂移的提交标记文件名。"""
return f".mememeow-{self.source_package}-source-commit"
_DINOV2_SOURCE_FILES = (
"dinov2/__init__.py",
"dinov2/hub/backbones.py",
"dinov2/models/vision_transformer.py",
)
_DINOV3_SOURCE_FILES = (
"dinov3/__init__.py",
"dinov3/hub/backbones.py",
"dinov3/models/vision_transformer.py",
)
VISUAL_MODEL_SPECS: dict[str, VisualModelSpec] = {
"dinov2_vits14": VisualModelSpec(
model="dinov2_vits14",
dimensions=384,
preprocess_version="dinov2_vits14-rgb224-first-frame-v1",
source_commit=DINOV2_SOURCE_COMMIT,
source_package="dinov2",
source_files=_DINOV2_SOURCE_FILES,
backbone_name="dinov2_vits14",
checkpoint_filename="dinov2_vits14_pretrain.pth",
checkpoint_url="https://dl.fbaipublicfiles.com/dinov2/dinov2_vits14/dinov2_vits14_pretrain.pth",
schema_revision="future-dinov2-vits14",
),
"dinov2_vitb14": VisualModelSpec(
model="dinov2_vitb14",
dimensions=768,
preprocess_version="dinov2_vitb14-rgb224-first-frame-v1",
source_commit=DINOV2_SOURCE_COMMIT,
source_package="dinov2",
source_files=_DINOV2_SOURCE_FILES,
backbone_name="dinov2_vitb14",
checkpoint_filename="dinov2_vitb14_pretrain.pth",
checkpoint_url="https://dl.fbaipublicfiles.com/dinov2/dinov2_vitb14/dinov2_vitb14_pretrain.pth",
schema_revision=ACTIVE_VISUAL_SCHEMA_REVISION,
runtime_supported=True,
),
"dinov2_vitl14": VisualModelSpec(
model="dinov2_vitl14",
dimensions=1024,
preprocess_version="dinov2_vitl14-rgb224-first-frame-v1",
source_commit=DINOV2_SOURCE_COMMIT,
source_package="dinov2",
source_files=_DINOV2_SOURCE_FILES,
backbone_name="dinov2_vitl14",
checkpoint_filename="dinov2_vitl14_pretrain.pth",
checkpoint_url="https://dl.fbaipublicfiles.com/dinov2/dinov2_vitl14/dinov2_vitl14_pretrain.pth",
schema_revision="future-dinov2-vitl14",
),
"dinov2_vitg14": VisualModelSpec(
model="dinov2_vitg14",
dimensions=1536,
preprocess_version="dinov2_vitg14-rgb224-first-frame-v1",
source_commit=DINOV2_SOURCE_COMMIT,
source_package="dinov2",
source_files=_DINOV2_SOURCE_FILES,
backbone_name="dinov2_vitg14",
checkpoint_filename="dinov2_vitg14_pretrain.pth",
checkpoint_url="https://dl.fbaipublicfiles.com/dinov2/dinov2_vitg14/dinov2_vitg14_pretrain.pth",
schema_revision="future-dinov2-vitg14",
),
"dinov3_vith16plus": VisualModelSpec(
model="dinov3_vith16plus",
dimensions=1280,
preprocess_version="dinov3_vith16plus-rgb224-first-frame-v1",
source_commit=DINOV3_SOURCE_COMMIT,
source_package="dinov3",
source_files=_DINOV3_SOURCE_FILES,
backbone_name="dinov3_vith16plus",
checkpoint_filename="dinov3_vith16plus_pretrain_lvd1689m-7c1da9a5.pth",
checkpoint_url="https://dl.fbaipublicfiles.com/dinov3/dinov3_vith16plus/dinov3_vith16plus_pretrain_lvd1689m-7c1da9a5.pth",
schema_revision="0008_dinov3_vith16plus",
runtime_supported=False,
),
}
def visual_model_spec(model: str) -> VisualModelSpec | None:
"""按模型标识返回清单项;未知标识交给测试夹具或未来扩展处理。"""
return VISUAL_MODEL_SPECS.get(str(model).strip())
def active_visual_model_spec() -> VisualModelSpec:
"""返回当前发布版本唯一允许加载的模型清单项。"""
return VISUAL_MODEL_SPECS[ACTIVE_VISUAL_MODEL_ID]
def source_repository_valid(source: str | Path | None, model: str) -> bool:
"""检查指定模型的官方源码最小文件集合和固定提交标记。"""
spec = visual_model_spec(model)
if spec is None or source is None:
return False
try:
root = Path(source).expanduser()
if not root.is_dir() or not all((root / relative).is_file() for relative in spec.source_files):
return False
marker = root / spec.source_marker_filename
return marker.is_file() and marker.read_text(encoding="ascii").strip() == spec.source_commit
except (OSError, TypeError, ValueError, UnicodeError):
return False