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
+17 -45
View File
@@ -1,6 +1,8 @@
"""Inference (S7): prompt revisions (REST), Call 1 vision classification, Call 2
content prose, test-inference, inference-off server description, inference_log.
Cites METADATA-35..115, SETTINGS-30/45/90.
overnight-whole-app: Call 1 POST is hard-disabled (410 call1_disabled). Call 2 stays.
"""
import base64
@@ -295,51 +297,21 @@ def _enabled(conn, key: str) -> bool:
@router.post("/slabs/{slab_id}/inference/call1")
async def call1(slab_id: str) -> dict:
conn = get_connection()
row = conn.execute("SELECT * FROM slabs WHERE id=? AND deleted_at IS NULL", (slab_id,)).fetchone()
if row is None:
return JSONResponse(status_code=404, content=_error("not_found", "Slab not found"))
if not _enabled(conn, "inference_enabled"):
return JSONResponse(status_code=409, content=_error("inference_disabled", "Inference is off"))
base, key, model = _inference_creds(conn)
if not base or not key:
return JSONResponse(status_code=409, content=_error("inference_unconfigured", "Inference is not configured"))
client = InferenceClient(base, key, model)
_seed_prompts(conn)
conn.commit()
act = _active_prompt(conn, "call1")
prompt_text = act[1] if act else CALL1_SEED
# Build vision message with processed photos (METADATA-35: long edge <= 1024) + taxonomy.
photos = conn.execute(
"SELECT id, seq, processed_blob FROM slab_photos "
"WHERE slab_id=? AND processed_blob IS NOT NULL ORDER BY seq LIMIT 8",
(slab_id,),
).fetchall()
image_parts = []
photo_meta: list[dict] = []
for p in photos:
blob = p["processed_blob"] if hasattr(p, "keys") else p[2]
pid = p["id"] if hasattr(p, "keys") else p[0]
seq = p["seq"] if hasattr(p, "keys") else p[1]
image_parts.append(_image_part_from_processed(blob))
photo_meta.append(_photo_meta_row(pid, seq, blob))
tax = _taxonomy_lists(conn)
text = (f"{prompt_text}\n\nLISTS:\n{json.dumps(tax, ensure_ascii=False)}\n\n"
f"SKU={row['sku']} length_in={row['length_in']} thickness_in={row['thickness_in']}")
messages = [{"role": "user", "content": image_parts + [{"type": "text", "text": text}]}]
t0 = time.time()
try:
raw = client.chat(messages)
except InferenceConnectionError as e:
return JSONResponse(status_code=503, content=_error("inference_unreachable", str(e), {"recoverable": True}))
except InferenceError as e:
return JSONResponse(status_code=502, content=_error("inference_failed", str(e), {"recoverable": True}))
latency = int((time.time() - t0) * 1000)
parsed = _parse_json(raw)
_log_call(conn, slab_id, 1, act[0] if act else None, model, messages, raw, latency, photo_meta)
# Apply confidence gate (METADATA-45).
suggestions = _gate(parsed)
return {"ok": True, "suggestions": suggestions}
"""Call 1 OUT (overnight-whole-app): hard-disabled. Call 2 stays.
Route retained so clients get an explicit 410 instead of a half-wired path.
Prompt seed / revision APIs for call1 remain for docs & future re-enable.
"""
_ = slab_id # unused while disabled
return JSONResponse(
status_code=410,
content=_error(
"call1_disabled",
"Call 1 (vision classification) is disabled on this branch. Use Call 2 for description text.",
{"call": 1, "disabled": True},
),
)
def _feat_display_name(name: str) -> str: