🔍 VisualMatch
AI-powered visual product search engine using OpenAI CLIP
Upload a product photo → get the matching item with a purchase link, instantly.
✨ What It Does
VisualMatch uses OpenAI CLIP (openai/clip-vit-base-patch32) to match user-uploaded product photos against an e-commerce catalog. It integrates with Instagram Direct via NovinHub webhooks, enabling customers to find and buy products directly from DMs.
Key features:
- 🧠 Real CLIP embeddings — 512-dimensional vectors, cosine similarity search
- 📸 Instagram DM bot — Conversational visual search via NovinHub webhooks
- ⚡ <100ms search latency — Brute-force vector search over pre-computed embeddings
- 🌐 Web dashboard — Built-in admin UI for catalog management and search testing
- 🐳 Docker ready — One-command deployment with Docker Compose
- 🔌 Extensible — Fan-out webhook router supports multiple bot services
🏗️ Architecture
visualmatch/
├── app/ # Application package
│ ├── main.py # FastAPI server & webhook handler
│ ├── config.py # Environment-driven configuration
│ ├── models/ # Pydantic data models
│ │ └── webhook.py
│ └── services/ # Core business logic
│ ├── clip_engine.py # CLIP embedding extraction
│ ├── catalog_service.py # Vector search over catalog
│ └── novinhub_client.py # NovinHub API client
├── scripts/ # Data pipeline utilities
│ ├── generate_live_catalog.py # Fetch products from live API
│ └── import_products.py # Import from Excel spreadsheet
├── tests/ # Pytest test suite
├── web/ # Web dashboard (HTML/CSS/JS)
├── docs/ # Documentation
│ ├── architecture.md # System design & diagrams
│ └── api.md # API reference
├── pyproject.toml # Python project configuration
├── Dockerfile # Multi-stage container build
├── docker-compose.yml # Container orchestration
├── Makefile # Development commands
└── .github/workflows/ci.yml # CI pipeline
See docs/architecture.md for detailed system diagrams and component documentation.
🚀 Quick Start
Prerequisites
- Python 3.10+
- (Optional) Docker
Local Setup
# Clone the repository
git clone https://github.com/your-org/visualmatch.git
cd visualmatch
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
make install
# Or manually: pip install -e ".[ml,import]"
# Configure environment
cp .env.example .env
# Edit .env — at minimum, set HF_TOKEN for CLIP model access
# Generate the product catalog (fetches from your API + computes embeddings)
make catalog-generate
# Start the server
make dev
The server starts at http://localhost:8000:
- 📖 API docs: http://localhost:8000/docs
- 🖥️ Web dashboard: http://localhost:8000/web/
Docker
cp .env.example .env
# Edit .env with your settings
docker compose up --build
📡 Webhook Setup
To connect with Instagram Direct via NovinHub:
- Create a NovinHub account and connect your Instagram Business page
- Set your webhook URL to:
https://your-domain.com/api/v1/novinhub-webhook - Configure your
.envfile:NOVINHUB_TOKEN=your_novinhub_api_token NOVINHUB_CHANNEL_ID=your_channel_id NOVINHUB_ACCOUNT_OWNER_ID=your_instagram_social_user_id - Set up an Icebreaker button in NovinHub with payload
FIND_MODEL
🔧 Catalog Generation
The system needs a product catalog with pre-computed CLIP embeddings. Two methods are available:
From Live API (Recommended)
Fetches products from your e-commerce API, downloads product images, and computes CLIP embeddings:
make catalog-generate
# Or: python -m scripts.generate_live_catalog
Note: You'll need to update the API URLs in
scripts/generate_live_catalog.pyto point to your own product API.
From Excel Spreadsheet
Place your product Excel file in data/ and run:
make catalog-import
# Or: python -m scripts.import_products
Excel format — Required columns:
| Column | Description |
|---|---|
شناسه محصول |
Product ID |
نام محصول |
Product name |
نام فارسی برند |
Brand name (Persian) |
نام انگلیسی برند |
Brand name (English) |
دسته بندی |
Category |
قیمت اولیه |
Price (Rials) |
⚙️ Configuration
All configuration is managed through environment variables. See .env.example for the complete list.
| Variable | Default | Description |
|---|---|---|
HF_TOKEN |
— | Hugging Face API token (for model download) |
CLIP_MODEL_NAME |
openai/clip-vit-base-patch32 |
CLIP model to use |
MATCH_THRESHOLD |
0.70 |
Minimum similarity for a match (0.0–1.0) |
FALLBACK_PRODUCT_URL |
— | Default product URL when no match is found |
NOVINHUB_TOKEN |
— | NovinHub API token |
NOVINHUB_ACCOUNT_OWNER_ID |
— | Your Instagram social_user_id |
AUTO_REPLY_ENABLED |
true |
Auto-reply via NovinHub |
LOG_LEVEL |
INFO |
Python logging level |
🧪 Testing
# Run full test suite
make test
# With coverage
make test-cov
# Lint & type check
make lint
📖 API Reference
Full API documentation is available at:
- Interactive: http://localhost:8000/docs (Swagger UI)
- Static: docs/api.md
Key Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/health |
System health check |
GET/POST |
/api/v1/novinhub-webhook |
NovinHub webhook handler |
GET/POST |
/api/novinhub/config |
Configuration management |
GET |
/api/logs |
Activity logs |
🤝 Contributing
Contributions are welcome! Please read CONTRIBUTING.md for development setup, code style, and the pull request process.
📄 License
This project is licensed under the MIT License.
Metadata
Release files for visualmatch 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| visualmatch-2.0.0.tar.gz | 2.6 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| visualmatch-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.6 MB
Release files / visualmatch-2.0.0.tar.gz
| Download URL | visualmatch-2.0.0.tar.gz |
|---|---|
| Size | 2.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
df4c47a08f6b5528fc707cf26ab8d69a66eaf8cbd386e1f0ce43a87197f10e93
|
|
BLAKE2b-256 checksum How to use checksums |
8b1acde30f23dd421e0e6424d01960211cd7b173705161e85080cbef2197fdba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Release files / visualmatch-2.0.0-py3-none-any.whl
| Download URL | visualmatch-2.0.0-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9d4d359147ac2cdb29e96f078e271d7d6bc8252c9af0e66d310e482facf56a32
|
|
BLAKE2b-256 checksum How to use checksums |
451bc13560204b5469bb457f1936acbbca60394da85e0cdfc643753773f5f28f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.2
|
Security for visualmatch 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.