Harden detection model asset selection
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-08 04:03:50 +02:00
parent 48ffcd0991
commit 0ed71c6f1e
7 changed files with 153 additions and 9 deletions
@@ -109,10 +109,20 @@ export function DetectionLab({
const detectionHasModel = selectedDetectionModel !== null
const detectionModelReady = Boolean(selectedDetectionModel?.configured)
const detectionModelUiRunnable = detectionModelReady && selectedDetectionModelId !== 'manual-fixture-detector'
const detectionHasExplicitModelAsset =
selectedDetectionModelId !== 'yolo-configured' || modelAssets.length === 0 || selectedModelAssetId.length > 0
const benchmarkCandidateAsset = modelAssets.find(
(asset) => asset.model_asset_id === 'geointel-building-yolov8s-hardneg160r4e50-pt',
)
const detectionHasTileManifest =
!detectionRequiresTileManifest || detectionTileManifestPath.trim().length > 0
const detectionRunReady =
Boolean(selectedProjectId) && detectionHasDataset && detectionHasModel && detectionModelUiRunnable && detectionHasTileManifest
Boolean(selectedProjectId) &&
detectionHasDataset &&
detectionHasModel &&
detectionModelUiRunnable &&
detectionHasExplicitModelAsset &&
detectionHasTileManifest
const detectionRunBlockedReason = !selectedProjectId
? 'Select or create a project first'
: !detectionHasDataset
@@ -123,6 +133,8 @@ export function DetectionLab({
? 'Fixture model is explicit test/demo-only'
: !detectionModelReady
? selectedDetectionModel?.limitation_message ?? 'Selected model is not configured'
: !detectionHasExplicitModelAsset
? 'Select a local model asset deliberately'
: !detectionHasTileManifest
? 'Provide a raster tile manifest for configured YOLO'
: null
@@ -193,17 +205,26 @@ export function DetectionLab({
<div className="ai-lab-model-surface" aria-label="Local model asset selection">
<div className="ai-lab-section-header">
<div>
<h3>Local model assets</h3>
<p>Select an existing model file mounted into the backend runtime. GeoIntel does not download model weights.</p>
<h3>Explicit model asset</h3>
<p>Local model assets are read-only. No model file is selected automatically. Choose an existing local model asset before submitting configured YOLO.</p>
</div>
<span className={selectedModelAsset ? 'status-badge status-badge-ready' : 'status-badge'}>
{selectedModelAsset ? 'asset selected' : 'using configured path'}
{selectedModelAsset ? 'asset selected' : 'no explicit asset'}
</span>
</div>
{benchmarkCandidateAsset ? (
<div className="model-asset-guidance">
<strong>Current benchmark candidate</strong>
<p>
{benchmarkCandidateAsset.display_name} is available for deliberate evaluation. Recommended starting threshold: 0.25.
Keep it operator-selected until hard-negative false positives are reduced.
</p>
</div>
) : null}
<label>
Local model file
<select value={selectedModelAssetId} onChange={(event) => onSelectModelAsset(event.target.value)}>
<option value="">Use configured YOLO_MODEL_PATH</option>
<option value="">Select explicit local model asset</option>
{modelAssets.map((asset) => (
<option key={asset.model_asset_id} value={asset.model_asset_id}>
{asset.display_name} {asset.active ? '(active)' : ''}
@@ -221,6 +242,8 @@ export function DetectionLab({
<div className="result-summary-card">
<p>File: {selectedModelAsset.filename}</p>
<p>Status: {selectedModelAsset.status}</p>
<p>Active runtime env model: {selectedModelAsset.active ? 'yes' : 'no'}</p>
<p>will_download_models: {selectedModelAsset.will_download_models ? 'yes' : 'no'}</p>
<p>Size: {formatModelAssetSize(selectedModelAsset.size_bytes)}</p>
<p>SHA-256: {selectedModelAsset.sha256.slice(0, 12)}</p>
<p>Path: {selectedModelAsset.model_path}</p>
@@ -340,6 +363,18 @@ export function DetectionLab({
: 'Not required for this model'}
</strong>
</div>
<div className={detectionHasExplicitModelAsset ? 'lab-readiness-item lab-readiness-item-ready' : 'lab-readiness-item'}>
<span>Local model asset</span>
<strong>
{selectedDetectionModelId === 'yolo-configured'
? selectedModelAsset
? selectedModelAsset.display_name
: modelAssets.length > 0
? 'Select a local model asset deliberately'
: 'No local assets reported; backend configured path only'
: 'Not required for this model'}
</strong>
</div>
</div>
</div>
<div className={detectionRunReady ? 'lab-action-guardrail lab-action-guardrail-ready' : 'lab-action-guardrail'}>
@@ -384,6 +419,11 @@ export function DetectionLab({
value={detectionConfidenceThreshold}
onChange={(event) => onSetConfidenceThreshold(Number(event.target.value))}
/>
{selectedDetectionModelId === 'yolo-configured' ? (
<span className="field-guidance">
Recommended starting threshold: 0.25 for the current local YOLOv8s benchmark candidate.
</span>
) : null}
</label>
</div>
{selectedDetectionModelId === 'yolo-configured' ? (