SQLModel: ORM Modern Python untuk Aplikasi AI yang Type-Safe
Dalam pengembangan aplikasi AI/ML, pengelolaan data di database adalah komponen krusial. Dari menyimpan hasil eksperimen, mengelola model registry, hingga tracking dataset versioning, semuanya membutuhkan interaksi database yang efisien dan type-safe. SQLModel, yang dibuat oleh Sebastián Ramírez (kreator FastAPI), menggabungkan kekuatan SQLAlchemy dan Pydantic untuk memberikan pengalaman ORM terbaik di Python.
Dalam tutorial ini, kita akan mempelajari SQLModel secara mendalam dan membangun sistem ML experiment tracking dan model registry yang siap produksi.
Apa Itu SQLModel?
SQLModel adalah library Python yang menggabungkan SQLAlchemy (ORM paling populer di Python) dengan Pydantic (library validasi data). Hasilnya adalah ORM yang:
- Type-safe: Full type hints dan autocompletion di IDE
- Validasi otomatis: Data divalidasi sebelum masuk database
- Kompatibel dengan FastAPI: Integrasi seamless karena kreator yang sama
- Sederhana: Satu class untuk model database DAN schema API
- Powerful: Akses penuh ke fitur SQLAlchemy jika dibutuhkan
Instalasi dan Setup
Instalasi SQLModel
pip install sqlmodel
Untuk database spesifik:
# PostgreSQL
pip install sqlmodel psycopg2-binary
MySQL
pip install sqlmodel pymysql
Async support
pip install sqlmodel aiosqlite asyncpg
Verifikasi
python -c "import sqlmodel; print(sqlmodel.version)"
Setup Database Engine
from sqlmodel import createengine, SQLModel
SQLite (development)
sqlite
url = "sqlite:///./mltracking.db"
engine = create
engine(sqliteurl, echo=True)
PostgreSQL (production)
postgres
url = "postgresql://user:password@localhost:5432/mltracking"
engine = create
engine(postgresurl, echo=False, poolsize=20, maxoverflow=10)
Buat semua tabel
SQLModel.metadata.create
all(engine)
Definisi Model
Model Dasar
from sqlmodel import Field, SQLModel, Session, select
from typing import Optional
from datetime import datetime
import uuid
class Experiment(SQLModel, table=True):
"""Model untuk ML Experiment"""
id: Optional[int] = Field(default=None, primarykey=True)
name: str = Field(index=True, minlength=1, maxlength=255)
description: Optional[str] = Field(default=None, maxlength=1000)
datasetname: str = Field(index=True)
algorithm: str
hyperparameters: Optional[str] = Field(default=None) # JSON string
accuracy: Optional[float] = Field(default=None, ge=0.0, le=1.0)
loss: Optional[float] = Field(default=None, ge=0.0)
status: str = Field(default="created", index=True)
createdat: datetime = Field(defaultfactory=datetime.utcnow)
updatedat: Optional[datetime] = Field(default=None)
createdby: str = Field(default="system")
class MLModel(SQLModel, table=True):
"""Model untuk Model Registry"""
tablename = "mlmodels"
id: Optional[int] = Field(default=None, primarykey=True)
name: str = Field(index=True, unique=True)
version: str = Field(default="1.0.0")
framework: str # pytorch, tensorflow, sklearn, etc.
modelpath: str
filesizemb: Optional[float] = Field(default=None)
inputschema: Optional[str] = Field(default=None)
outputschema: Optional[str] = Field(default=None)
isactive: bool = Field(default=True, index=True)
createdat: datetime = Field(defaultfactory=datetime.utcnow)
class Dataset(SQLModel, table=True):
"""Model untuk Dataset Registry"""
id: Optional[int] = Field(default=None, primarykey=True)
name: str = Field(index=True)
version: str = Field(default="1.0")
filepath: str
rowcount: Optional[int] = Field(default=None)
columncount: Optional[int] = Field(default=None)
fileformat: str = Field(default="csv")
description: Optional[str] = Field(default=None)
createdat: datetime = Field(defaultfactory=datetime.utcnow)