Files
vector-search-demo/oravector-demo/backend/main_oracle_indb.py
T
dierk 1c5e00d8e4 Add targeted comments explaining non-obvious behaviour
- embedder.py: lazy model load rationale, RGB conversion, shared vector space
- main.py: why vec appears twice, ::vector cast, 1-distance score formula
- main_oracle.py: why array.array("f") is required instead of plain list
- main_oracle_indb.py: no embedder import — embedding done inside Oracle SQL
- index_images_oracle.py: same array.array requirement on indexing path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:39:40 +02:00

62 lines
2.0 KiB
Python

# No embedder import — text embedding happens inside Oracle via VECTOR_EMBEDDING(CLIP_TXT).
# The only value Python passes to the database is the raw query string (:q).
import os
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from dotenv import load_dotenv
from db_oracle import get_connection_indb
load_dotenv()
PHOTOS_DIR = os.getenv("PHOTOS_DIR")
FRONTEND_DIR = os.path.join(os.path.dirname(__file__), "../../oravector-demo/frontend/indb")
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
app.mount("/ui", StaticFiles(directory=os.path.abspath(FRONTEND_DIR), html=True), name="ui")
@app.get("/search")
def search(q: str = Query(...), limit: int = Query(12)):
conn = get_connection_indb()
cur = conn.cursor()
cur.execute(
"""
SELECT filename,
1 - VECTOR_DISTANCE(
foto_vek,
VECTOR_EMBEDDING(CLIP_TXT USING :q AS data),
COSINE
) AS score
FROM VECTOR.FOTO_VEKTOR
ORDER BY VECTOR_DISTANCE(
foto_vek,
VECTOR_EMBEDDING(CLIP_TXT USING :q AS data),
COSINE
)
FETCH FIRST :lim ROWS ONLY
""",
{"q": q, "lim": limit},
)
rows = cur.fetchall()
cur.close()
conn.close()
return [{"filename": r[0], "score": round(r[1], 4)} for r in rows]
@app.get("/stats")
def stats():
conn = get_connection_indb()
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM VECTOR.FOTO_VEKTOR")
count = cur.fetchone()[0]
cur.close()
conn.close()
return {"count": count}
@app.get("/photos/{filename}")
def get_photo(filename: str):
path = os.path.join(PHOTOS_DIR, filename)
return FileResponse(path, media_type="image/jpeg")