A fullโstack application for searching and recommending fashion products using semantic vector search over images and text.
google/vit-base-patch16-224-in21k (ViTโBase, 768โdim)sentence-transformers/all-MiniLM-L6-v2 (384โdim)paramaggarwal/fashion-product-images-smallparamaggarwal/fashion-product-images-datasetOracle VecDB acts as the retrieval layer of the application. Image embeddings and text embeddings are stored in separate dense vector tables, and query-time similarity search is combined with metadata filtering to return relevant fashion products in real time.
This sample uses Oracle VecDB as the vector retrieval backbone for both text-based and image-based fashion search. Separate dense vector tables are used for each modality, while shared metadata enables consistent filtering and product presentation across both search modes.
gender, masterCategory, and subCategoryEnsure you have your Kaggle API key set up and the Kaggle CLI (or kagglehub) working to download datasets before proceeding.
Oracle VecDB configuration is controlled via environment variables.
backend/.env.example to backend/.env.VECDB_REST_URL, VECDB_USERNAME, and VECDB_PASSWORD entries with your real VecDB endpoint and credentials.backend/.env out of source control.config.py loads these values automatically:
from dotenv import load_dotenv
load_dotenv(override=True)
ORACLE_VECDB_REST_URL = os.getenv("VECDB_REST_URL")
ORACLE_USERNAME = os.getenv("VECDB_USERNAME")
ORACLE_PASSWORD = os.getenv("VECDB_PASSWORD")
ORACLE_ACCESS_TOKEN = os.getenv("VECDB_ACCESS_TOKEN")
You can still override other settings (e.g., ORACLE_IMAGE_TABLE, ORACLE_TEXT_TABLE) via environment variables if needed.
This is also how the backend switches between the SMALL and HIGH Oracle VecDB tables at runtime.
Requirement: Python 3.10+
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cd frontend
npm install
The application supports two dataset modes:
The selected mode determines which Oracle VecDB image and text tables are used by the backend.
cd backend
python load_dataset.py --dataset small
Notes
FASHION_IMAGE_SMALL / FASHION_TEXT_SMALL.BACKEND_ORIGIN=http://<your_vm_ip_addrs>:8000 uvicorn main:app --host 0.0.0.0 --port 8000
The backend defaults to SMALL tables in backend/config.py.
cd frontend
VITE_API_URL=http://<your_vm_ip_addrs>:8000 npm run dev -- --host 0.0.0.0 --port 5173
cd backend
python load_dataset.py --dataset high
ORACLE_IMAGE_TABLE=FASHION_IMAGE_HIGH ORACLE_TEXT_TABLE=FASHION_TEXT_HIGH \
BACKEND_ORIGIN=http://<your_vm_ip_addrs>:8000 uvicorn main:app --host 0.0.0.0 --port 8000
VITE_API_URL=http://<your_vm_ip_addrs>:8000 npm run dev -- --host 0.0.0.0 --port 5173).Switch back to SMALL any time by starting uvicorn without overrides:
BACKEND_ORIGIN=http://<your_vm_ip_addrs>:8000 uvicorn main:app --host 0.0.0.0 --port 8000
Tip: if you previously exported env vars, unset ORACLE_IMAGE_TABLE ORACLE_TEXT_TABLE first.
fashion_products_search/
โโโ backend/
โ โโโ .env.example
โ โโโ config.py
โ โโโ load_dataset.py
โ โโโ main.py
โ โโโ requirements.txt
โโโ frontend/
โ โโโ .bolt/
โ โโโ src/
โ โ โโโ components/
โ โ โโโ data/
โ โ โโโ services/
โ โ โโโ types/
โ โ โโโ App.tsx
โ โ โโโ index.css
โ โ โโโ main.tsx
โ โ โโโ vite-env.d.ts
โ โโโ .gitignore
โ โโโ eslint.config.js
โ โโโ index.html
โ โโโ package-lock.json
โ โโโ package.json
โ โโโ postcss.config.js
โ โโโ tailwind.config.js
โ โโโ tsconfig.app.json
โ โโโ tsconfig.json
โ โโโ tsconfig.node.json
โ โโโ vite.config.ts
โโโ images/
โ โโโ architecture.png
โ โโโ screenshot.png
โโโ README.md
These two Oracle VecDB tables are intentionally separated because image and text embeddings use different models and different vector dimensions. Both tables store the same product metadata, allowing consistent filtering and display logic across both search modes.
ORACLE_IMAGE_TABLE โ 768 dimensions (ViT), metric cosine.ORACLE_TEXT_TABLE โ 384 dimensions (MiniLM), metric cosine.Each indexed product vector stores shared metadata, including:
gendermasterCategorysubCategoryarticleTypebaseColourseasonyearusageproductDisplayNameimage_pathThis shared metadata schema allows both text-based and image-based search results to use the same filtering and presentation logic.
google/vit-base-patch16-224-in21k
sentence-transformers/all-MiniLM-L6-v2
Oracle VecDB metadata filters are applied at query time (serverโside). Example filters:
{"gender": {"$eq": "Men"}}
{"$and": [
{"gender": {"$eq": "Men"}},
{"masterCategory": {"$eq": "Apparel"}}
]}
The backend accepts raw filter values (e.g., gender: "Men") and builds canonical Oracle VecDB filters with $eq / $in and $and.
/search/text
{ "query": string, "top_k": number, "filters"?: object }{ results: SearchResult[] } with imageUrl, metadata, and similarityScore./search/image
multipart/form-data with file, top_k, optional filters (JSON string).{ results: SearchResult[] }./images/{id}
image_path).The /images/{id} endpoint resolves the local image_path stored in Oracle VecDB metadata and streams the product image to the frontend.
Highโlevel steps followed to build the two Oracle VecDB indexes.
kagglehub.
paramaggarwal/fashion-product-images-small (root myntradataset/)paramaggarwal/fashion-product-images-dataset (root fashion-dataset/)
Locate images under /images and metadata in styles.csv.Assemble image table: Scan the images directory to create a DataFrame with filename, id (filename stem), and absolute path to each .jpg file.
Load product metadata: Read styles.csv with id as string and innerโjoin on id to attach fields such as gender, masterCategory, subCategory, articleType, baseColour, season, year, usage, and productDisplayName to each image.
Clean & validate: Keep rows whose image path exists on disk and whose productDisplayName is present; drop bad/empty entries and fill remaining NaNs with empty strings.
google/vit-base-patch16-224-in21k (ViTโBase). Extract the CLS token (768โdim) and L2โnormalize.sentence-transformers/all-MiniLM-L6-v2 (384โdim) for product titles.FASHION_IMAGE_SMALL / FASHION_TEXT_SMALLFASHION_IMAGE_HIGH / FASHION_TEXT_HIGHDefine shared metadata schema: For every item, store gender, masterCategory, subCategory, articleType, baseColour, season, year, usage, productDisplayName, and image_path (local file path used by the backend to stream images).
values (embedding), and the shared metadata.{"$and": [
{"gender": {"$eq": "Men"}},
{"masterCategory": {"$eq": "Apparel"}}
]}
{"gender": {"$in": ["Men", "Boys"]}}
Fashion product search UI with text search, image upload, top-k retrieval, and metadata filters.