oracle-ai-developer-hub

Fashion Product Search | Multimodal Semantic Search with Oracle VecDB

A fullโ€‘stack application for searching and recommending fashion products using semantic vector search over images and text.

๐Ÿš€ Overview

Oracle 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.


๐Ÿงญ Architecture Flow

  1. The indexing pipeline downloads and prepares the fashion dataset from Kaggle.
  2. Product metadata is merged with image files from the dataset.
  3. Image embeddings are generated with ViT and stored in an Oracle VecDB image table.
  4. Text embeddings are generated from product titles with Sentence-Transformers and stored in an Oracle VecDB text table.
  5. Users can search either by text description or by uploading an image.
  6. Oracle VecDB performs top-k similarity search against the appropriate vector table.
  7. Optional metadata filters such as gender, masterCategory, and subCategory are applied server-side.
  8. The backend returns ranked products with metadata and image URLs for frontend display.


Why Oracle VecDB in this sample

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.


๐Ÿ’ก Features


Preโ€‘Installation

Ensure you have your Kaggle API key set up and the Kaggle CLI (or kagglehub) working to download datasets before proceeding.


๐Ÿ› ๏ธ Configuration

Oracle VecDB configuration is controlled via environment variables.

VecDB environment variables

  1. Copy backend/.env.example to backend/.env.
  2. Replace the placeholder VECDB_REST_URL, VECDB_USERNAME, and VECDB_PASSWORD entries with your real VecDB endpoint and credentials.
  3. Keep 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.


๐Ÿ› ๏ธ Installation

Backend Setup (FastAPI + Oracle VecDB)

Requirement: Python 3.10+

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Frontend Setup (React/Vite)

cd frontend
npm install

๐Ÿ”„ Run (Small by default, High on demand)

Dataset Mode Selection

The application supports two dataset modes:

The selected mode determines which Oracle VecDB image and text tables are used by the backend.

1) Index SMALL (default)

cd backend
python load_dataset.py --dataset small

Notes

2) Start Backend (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.

3) Start Frontend

cd frontend
VITE_API_URL=http://<your_vm_ip_addrs>:8000 npm run dev -- --host 0.0.0.0 --port 5173

Use HIGH (highโ€‘resolution) instead

  1. Index HIGH once:
    cd backend
    python load_dataset.py --dataset high
    
  2. Start backend pointing to HIGH tables (inline env for a oneโ€‘off switch):
    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
    
  3. Frontend: refresh the browser (or start with 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.


๐Ÿ“‚ Project Structure

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

๐Ÿ“Š Vector Database Configuration (Oracle VecDB)

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.


Stored Metadata

Each indexed product vector stores shared metadata, including:

This shared metadata schema allows both text-based and image-based search results to use the same filtering and presentation logic.


๐Ÿ”ง Embedding Models


๐Ÿ” Metadata Filtering

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.


Query Flow

  1. Encode the user query with Sentence-Transformers
  2. Query the Oracle VecDB text table
  3. Apply optional metadata filters
  4. Return ranked products with metadata and image URLs
  1. Load and preprocess the uploaded image
  2. Encode the image with ViT
  3. Query the Oracle VecDB image table
  4. Apply optional metadata filters
  5. Return visually similar products with metadata and image URLs

๐Ÿ“ก API Endpoints (Backend)

The /images/{id} endpoint resolves the local image_path stored in Oracle VecDB metadata and streams the product image to the frontend.


๐Ÿ“ฆ Indexing Pipeline (Kaggle Myntra)

Highโ€‘level steps followed to build the two Oracle VecDB indexes.

  1. Download dataset: Fetch via kagglehub.
    • SMALL: paramaggarwal/fashion-product-images-small (root myntradataset/)
    • HIGH: paramaggarwal/fashion-product-images-dataset (root fashion-dataset/) Locate images under /images and metadata in styles.csv.
  2. Assemble image table: Scan the images directory to create a DataFrame with filename, id (filename stem), and absolute path to each .jpg file.

  3. 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.

  4. 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.

  5. Initialize embedding models:
    • Image model: google/vit-base-patch16-224-in21k (ViTโ€‘Base). Extract the CLS token (768โ€‘dim) and L2โ€‘normalize.
    • Text model: sentence-transformers/all-MiniLM-L6-v2 (384โ€‘dim) for product titles.
  6. Prepare Oracle VecDB tables: Ensure the Oracle VecDB tables exist with appropriate dimensions and index parameters. By default the loader writes to:
    • SMALL: FASHION_IMAGE_SMALL / FASHION_TEXT_SMALL
    • HIGH: FASHION_IMAGE_HIGH / FASHION_TEXT_HIGH
  7. Define 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).

  8. Batch embed & upsert: Iterate over the DataFrame in batches (e.g., 256):
    • Load images โ†’ compute image embeddings; take product titles โ†’ compute text embeddings.
    • Build vectors with string IDs, values (embedding), and the shared metadata.
    • Upsert image vectors to the image index; upsert text vectors to the text index.
  9. Result: Two synchronized modalityโ€‘specific indexes (image/text) sharing identical metadata, enabling crossโ€‘modal search and precise metadata filtering in Oracle VecDB.

Notes

๐Ÿงช Example Filters


Current Limitations


๐Ÿ–ผ๏ธ UI Screenshot

Fashion product search UI with text search, image upload, top-k retrieval, and metadata filters.