Make cross-check and reuse-as-seg the service default

Cross-check + reuse-as-seg are already the config/CLI default; align the HTTP
service with them instead of forcing cross-check off. The earlier off-by-default
was to avoid the extra inference, but reuse-as-seg now makes that forward double
as the seg mask (birefnet backend) -- it replaces the primary seg model rather
than adding to it, so the cost concern is gone.

- app.py: honour the config default (on); BGFILTER_CROSS_CHECK still forces
  either way, unset = config.
- service.py preload: warm the cross-check HR-matting model, and skip the now-
  redundant primary segmenter when reuse covers segmentation.
- README / DEPLOY(_ZH): document cross-check as default-on, BiRefNet_HR-matting
  as required (not optional), BGFILTER_CROSS_CHECK=0 to disable.

Verified: service defaults cross_check on, env forces both ways, preload picks
cross-checker and skips the primary segmenter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 16:11:43 +08:00
parent c19a35de80
commit ad445611ad
5 changed files with 52 additions and 41 deletions
+13 -3
View File
@@ -38,10 +38,20 @@ class PipelineManager:
if preload:
if base_settings.model.matting_method == "vitmatte":
self._get_runner()
if base_settings.segmentation.enabled:
# Cross-check is default behaviour, so its HR-matting model is part of
# the warm set. With reuse-as-seg on the birefnet backend that same
# forward also serves as the seg mask, so the primary segmenter is
# never used on the default path -- only preload it when reuse won't
# cover segmentation (reuse off, or a non-birefnet default backend).
if base_settings.cross_check.enabled:
self._get_cross_checker()
reuse_covers_seg = (
base_settings.cross_check.enabled
and base_settings.cross_check.reuse_as_seg
and base_settings.segmentation.backend == "birefnet"
)
if base_settings.segmentation.enabled and not reuse_covers_seg:
self._get_segmenter(base_settings.segmentation.backend)
# The cross-check model is deliberately NOT preloaded: it is opt-in
# per request, so the first request that enables it pays the load.
@property
def default_seg_model(self) -> str: