chore(inference): disable Call 1 end-to-end; Call 2 stays

overnight-whole-app: Call 1 (vision classification) is OUT.
- POST /api/v1/slabs/{id}/inference/call1 always returns 410 call1_disabled
  (no model chat, no inference_log). Prompt seed/revision APIs kept dormant.
- Review: remove "Suggest with AI" / runInference (inferTaxon).
- GenerateText: remove Classify metadata (Call 1) button; Call 2 generate stays.
- PROMPTS.md banner documents Call 1 OUT / Call 2 STAYS.
- Settings: inference_enabled toggle annotated as Call-1 latch (dormant).
- Backend tests updated to assert 410; Call 2 tests unchanged.
This commit is contained in:
grokbot_ty
2026-09-25 17:46:39 -07:00
parent 60700b47fb
commit 087557f89f
7 changed files with 57 additions and 218 deletions
+2 -1
View File
@@ -5,7 +5,7 @@
// photos.py POST/GET /api/v1/slabs/{id}/photos[.../original|processed]
// review.py POST /api/v1/slabs/{id}/review
// publish.py POST /api/v1/slabs/{id}/publish
// inference.py POST /api/v1/slabs/{id}/inference/call1|call2
// inference.py POST /api/v1/slabs/{id}/inference/call1 (DISABLED 410) | call2
// settings.py GET/PUT /api/v1/settings ; POST /api/v1/settings/test-woo|test-inference
// taxonomy.py GET/POST /api/v1/admin/taxonomy[.../sync]
// pricing.py CRUD /api/v1/admin/pricing[/{id}]
@@ -332,6 +332,7 @@ export interface Call2Result {
description: string;
}
/** Call 1 OUT (overnight-whole-app): always fails with 410 call1_disabled. Prefer manual taxonomy. */
export function inferTaxon(slabId: string): Promise<Call1Result> {
return fetch(`/api/v1/slabs/${encodeURIComponent(slabId)}/inference/call1`, {
method: 'POST',
@@ -3,7 +3,6 @@
let contentEnabled = false;
let reachable = false;
let description: string | null = null;
let call1Suggestions: Record<string, unknown> | null = null;
let error = '';
let busy = false;
@@ -41,25 +40,6 @@
busy = false;
}
async function classify() {
if (!slabId) {
error = 'Enter a slab id.';
return;
}
busy = true;
error = '';
call1Suggestions = null;
try {
const res = await fetch(`/api/v1/slabs/${encodeURIComponent(slabId)}/inference/call1`, { method: 'POST' });
const body = await res.json();
if (res.ok) call1Suggestions = body.suggestions;
else error = body.error?.message || `call1 failed (${res.status})`;
} catch {
error = 'network error';
}
busy = false;
}
checkReadiness();
</script>
@@ -68,6 +48,7 @@
<p class="state">
Content generation: {contentEnabled ? 'on' : 'off'} · endpoint: {reachable ? 'reachable' : 'unreachable'}
</p>
<p class="note">Call 1 (vision classification) is disabled on this branch. Call 2 description generation stays.</p>
{#if !contentEnabled || !reachable}
<p class="note">The Generate text control is disabled: it appears only when content generation is
enabled and the inference endpoint is reachable.</p>
@@ -78,13 +59,9 @@
</div>
<div class="row">
<button on:click={generate} disabled={busy}>{busy ? 'Working…' : 'Generate description (Call 2)'}</button>
<button on:click={classify} disabled={busy}>Classify metadata (Call 1)</button>
</div>
{#if error}<p class="err">{error}</p>{/if}
{#if description}<p class="desc">{description}</p>{/if}
{#if call1Suggestions}
<pre class="sug">{JSON.stringify(call1Suggestions, null, 2)}</pre>
{/if}
{/if}
<button class="mini" on:click={checkReadiness}>Recheck readiness</button>
</div>
@@ -98,6 +75,5 @@
.note { color: #e8a; }
.err { color: #e88; }
.desc { margin-top: 12px; }
.sug { background: #1c1c1c; padding: 8px; }
.mini { margin-top: 12px; font-size: 12px; }
</style>
+4 -47
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import { onMount, onDestroy, tick } from 'svelte';
import {
getSlab, updateSlab, reviewSlab, getTaxonomy, getSettings, inferTaxon, inferContent,
getSlab, updateSlab, reviewSlab, getTaxonomy, getSettings, inferContent,
listPhotos, persistLineup, photoUrl, ApiError,
type Slab, type Taxonomy, type TaxCategory, type TaxTag, type SettingsView, type PhotoRow,
} from '../../api/slabs';
@@ -143,8 +143,6 @@
let commitToken = 0;
// --- Inference ---
let aiBusy = false;
let aiNote = '';
let genBusy = false;
let genError = '';
let canGenerateContent = false;
@@ -346,7 +344,7 @@
aiRecommendations.push(...(s.figure_term_ids ?? []));
}
// AI-marked option views (badge on rows after Call 1 / stored confidences).
// AI-marked option views (legacy Call 1 badges; Call 1 disabled on this branch).
$: speciesOptsView = speciesOpts.map((o) => ({ ...o, ai: aiRecommendations.includes(o.id) }));
$: woodCatGroupsView = woodCatGroups.map((g) => ({
parent: g.parent,
@@ -494,40 +492,6 @@
}
}
async function runInference() {
if (!slab) return;
aiBusy = true;
aiNote = '';
try {
const r = await inferTaxon(slabId);
const s = r.suggestions;
const recs: number[] = [];
if (s.species_id) { speciesSel = String(s.species_id); recs.push(s.species_id); }
if (s.wood_category_ids) {
woodCatIds = [...s.wood_category_ids];
primaryCatId = nextPrimary(woodCatIds, primaryCatId);
recs.push(...s.wood_category_ids);
}
if (s.edge_type_term_id) edgeSel = String(s.edge_type_term_id);
if (s.figure_term_ids) { figureIds = [...s.figure_term_ids]; recs.push(...s.figure_term_ids); }
if (s.feature_tag_ids?.length) {
featTagIds = [...s.feature_tag_ids];
recs.push(...s.feature_tag_ids);
}
// Grade is not AI-suggested (METADATA-40) — owner judgment. Do not auto-fill.
aiRecommendations = recs;
aiNote = recs.length ? `AI suggested ${recs.length} field${recs.length === 1 ? '' : 's'} — review & edit below.` : 'No confident AI suggestions.';
await commitReview();
// #90: force the <select> DOM to reflect the prefilled values after Svelte's
// own select_option(reset) has run.
syncSelects();
} catch (e) {
aiNote = e instanceof ApiError ? e.message : 'Inference unavailable.';
} finally {
aiBusy = false;
}
}
async function generateContent() {
if (!slab || !canCreateDesc) return;
genBusy = true;
@@ -687,14 +651,7 @@
</div>
{/if}
{#if settings?.inference_enabled}
<div class="aibar">
<button type="button" class="ai-btn" data-testid="run-inference" on:click={runInference} disabled={aiBusy}>
{aiBusy ? 'Reading slab…' : 'Suggest with AI'}
</button>
{#if aiNote}<p class="ai-note" data-testid="ai-note">{aiNote}</p>{/if}
</div>
{/if}
<!-- Call 1 OUT (overnight-whole-app): Suggest-with-AI removed. Call 2 generateContent stays. -->
<!-- Species (single, AI-assist) -->
<div class="field">
@@ -793,7 +750,7 @@
/>
</div>
<!-- feat-* product tags (optional, AI-assisted by Call 1) -->
<!-- feat-* product tags (optional; Call 1 assist disabled on this branch) -->
<div class="field">
<label class="lbl">feat-* tags <span class="sug">optional</span> <span class="ai">AI assist</span></label>
<MultiSelect
+1 -1
View File
@@ -326,7 +326,7 @@
</div>
<div>
<label><input type="checkbox" bind:checked={form.inference_enabled} /> Inference Enabled (default false)</label>
<label><input type="checkbox" bind:checked={form.inference_enabled} /> Inference Enabled (Call 1 — DISABLED on this branch; toggle kept for settings round-trip)</label>
</div>
<div>