GET api update for image vector

This commit is contained in:
sriram
2026-09-18 17:50:14 +05:30
parent d6296bd1f0
commit bc786b1c49
6 changed files with 255 additions and 2 deletions

View File

@@ -23,7 +23,13 @@ from app.infrastructure.settings import (
)
from app.services import image_embedder
from app.services.catalog_search import search_catalog
from app.services.image_match import ImageSearchResult, InvalidVectorError, search_by_vector
from app.services.image_match import (
ImageSearchResult,
InvalidVectorError,
normalise_vector,
parse_vector_param,
search_by_vector,
)
router = APIRouter(tags=["search"])
@@ -117,6 +123,39 @@ def image_vector_search_endpoint(body: ImageVectorSearchRequest) -> ImageSearchO
return _to_image_search_out(result)
@router.get("/search/image-vector", response_model=ImageSearchOut)
def image_vector_search_get_endpoint(
vector: str = Query(
..., min_length=1, max_length=16_000,
description="The 1024-float embedding: comma-separated decimals, or urlsafe base64 of "
"1024 little-endian float32 (recommended - 5.5 KB instead of 8-10 KB)",
),
text: Optional[str] = Query(None, max_length=500, description="OCR text read off the label"),
brand: Optional[str] = Query(None, max_length=120, description="Restrict to one brand (no fallback)"),
category: Optional[str] = Query(None, max_length=120),
top_k: int = Query(IMAGE_SEARCH_DEFAULT_TOP_K, ge=1, le=IMAGE_SEARCH_MAX_TOP_K),
min_score: float = Query(IMAGE_SEARCH_DEFAULT_MIN_SCORE, ge=-1.0, le=1.0),
) -> ImageSearchOut:
"""The POST above as a GET, for clients that can only pass a query string.
Same ranking, same response. The vector is 1024 floats, so the URL is
5.5 KB as base64 or 8-10 KB comma-separated: fine through the API host
(Traefik -> uvicorn, which serve.py gives 64 KB of request-line room),
but the comma form exceeds the 8 KB nginx allows on the app domain. Use
base64, or the POST, for anything that has to work everywhere.
"""
try:
# Validated here, not only inside the service, so this route rejects a
# short / NaN / zero vector exactly as the POST's schema does.
values = normalise_vector(parse_vector_param(vector))
result = search_by_vector(
values, text=text, brand=brand, category=category, top_k=top_k, min_score=min_score,
)
except InvalidVectorError as exc:
raise HTTPException(status_code=422, detail=str(exc))
return _to_image_search_out(result)
@router.post("/search/image", response_model=ImageSearchOut)
async def image_search_endpoint(
file: UploadFile = File(..., description="The product photo (JPEG/PNG/WebP), ideally cropped to the pack"),