mri-inference-api / database.py
sezer-muhammed's picture
feat: add fold metadata and paginated results
3de92d7
Raw
History Blame Contribute Delete
3.87 kB
import os
from datetime import datetime
import libsql_client
_state: dict = {}
async def init():
_state["client"] = libsql_client.create_client(
url=os.environ["TURSO_DATABASE_URL"],
auth_token=os.environ["TURSO_AUTH_TOKEN"],
)
await _state["client"].execute("""
CREATE TABLE IF NOT EXISTS inference_results (
id INTEGER PRIMARY KEY AUTOINCREMENT,
filename TEXT NOT NULL,
model_name TEXT NOT NULL,
centiloid REAL,
raw_output REAL,
label TEXT,
fold INTEGER,
created_at TEXT NOT NULL,
UNIQUE (filename, model_name)
)
""")
await _ensure_fold_column()
async def _ensure_fold_column() -> None:
rs = await _state["client"].execute("PRAGMA table_info(inference_results)")
cols = [row[1] for row in rs.rows]
if "fold" not in cols:
await _state["client"].execute(
"ALTER TABLE inference_results ADD COLUMN fold INTEGER"
)
async def save_result(
filename: str,
model_name: str,
centiloid: float,
raw_output: float,
label: str | None = None,
fold: int | None = None,
) -> int:
now = datetime.utcnow().isoformat()
rs = await _state["client"].execute(
"INSERT INTO inference_results"
" (filename, model_name, centiloid, raw_output, label, fold, created_at)"
" VALUES (?, ?, ?, ?, ?, ?, ?)"
" ON CONFLICT(filename, model_name) DO UPDATE SET"
" centiloid = excluded.centiloid,"
" raw_output = excluded.raw_output,"
" label = excluded.label,"
" fold = COALESCE(excluded.fold, inference_results.fold),"
" created_at = excluded.created_at",
[filename, model_name, centiloid, raw_output, label, fold, now],
)
return rs.last_insert_rowid
async def get_results_page(
limit: int,
offset: int,
fold: int | None = None,
) -> tuple[int, list[dict]]:
where = ""
params: list = []
if fold is not None:
where = " WHERE fold = ?"
params.append(fold)
count_rs = await _state["client"].execute(
f"SELECT COUNT(*) AS count FROM inference_results{where}",
params,
)
total = int(count_rs.rows[0][0])
rs = await _state["client"].execute(
"SELECT id, filename, model_name, centiloid, raw_output, label, fold, created_at"
f" FROM inference_results{where} ORDER BY created_at DESC LIMIT ? OFFSET ?",
[*params, limit, offset],
)
cols = [c.name if hasattr(c, "name") else c for c in rs.columns]
return total, [dict(zip(cols, row)) for row in rs.rows]
async def get_done_pairs() -> list[dict]:
rs = await _state["client"].execute(
"SELECT filename, model_name FROM inference_results"
)
cols = [c.name if hasattr(c, "name") else c for c in rs.columns]
return [dict(zip(cols, row)) for row in rs.rows]
async def get_folds() -> list[int]:
rs = await _state["client"].execute(
"SELECT DISTINCT fold FROM inference_results"
" WHERE fold IS NOT NULL ORDER BY fold ASC"
)
return [int(row[0]) for row in rs.rows]
async def update_result_fold_by_id(row_id: int, fold: int | None) -> bool:
rs = await _state["client"].execute(
"UPDATE inference_results SET fold = ? WHERE id = ?",
[fold, row_id],
)
return rs.rows_affected > 0
async def update_result_fold_by_pair(
filename: str,
model_name: str,
fold: int | None,
) -> bool:
rs = await _state["client"].execute(
"UPDATE inference_results SET fold = ? WHERE filename = ? AND model_name = ?",
[fold, filename, model_name],
)
return rs.rows_affected > 0
async def close():
if "client" in _state:
await _state["client"].close()