Sebagian besar tutorial embedding hanya membahas text. Tapi di production nyata, data tidak datang dalam satu modalitas — ada gambar produk, rekaman suara, dokumen PDF, dan teks sekaligus. Ini cara membangun pipeline yang menyatukan semuanya.
Multimodal Embedding — Satu Vector Space untuk Semua Modalitas
Pilihan Model Embedding per Modalitas
| Modalitas | Model | Harga | Dimensi | Catatan untuk Indonesia |
|---|---|---|---|---|
| Teks | Cohere embed-multilingual-v3 | $0.10/1M token | 1024 | Terbaik untuk Bahasa Indonesia |
| OpenAI text-embedding-3-small | $0.02/1M token | 1536 | Cukup untuk Indonesia, murah | |
| intfloat/multilingual-e5 (OSS) | $0 (self-hosted) | 768 | Good quality, gratis | |
| Gambar | OpenAI CLIP (ViT-L/14) | $0 (open weight) | 768 | Standar industri untuk image-text |
| Google SigLIP | $0 (open weight) | 1152 | Lebih baik dari CLIP, masih OSS | |
| Cloudflare Workers AI CLIP | $0.011/1K gambar | 512 | Mudah deploy, edge Indonesia | |
| Audio | Whisper → text → embed (2-step) | $0.006/menit audio | — | Paling reliable untuk Indonesia, Whisper support Bahasa Indonesia |
| Clap (audio embedding langsung) | $0 (OSS) | 512 | Lebih advanced tapi setup lebih complex |
Use Case Konkret untuk Pasar Indonesia
Implementasi Pipeline Hybrid (Text + Image)
from PIL import Image
import torch
import clip
from sentence_transformers import SentenceTransformer
import numpy as np
class MultimodalEmbedder:
def __init__(self):
# Text: multilingual-e5 untuk support Bahasa Indonesia
self.text_model = SentenceTransformer("intfloat/multilingual-e5-large")
# Image: SigLIP lebih baik dari CLIP untuk akurasi
self.clip_model, self.clip_preprocess = clip.load("ViT-L/14")
self.clip_model.eval()
# Projection layer untuk align dimensi (text 1024, CLIP 768)
self.text_dim = 1024
self.image_dim = 768
self.unified_dim = 768 # target: project ke dimensi yang sama
def embed_text(self, text: str) -> np.ndarray:
# E5 perlu prefix untuk performance terbaik
vec = self.text_model.encode(f"query: {text}", normalize_embeddings=True)
return self._project_text(vec)
def embed_image(self, image_path: str) -> np.ndarray:
image = Image.open(image_path)
image_input = self.clip_preprocess(image).unsqueeze(0)
with torch.no_grad():
features = self.clip_model.encode_image(image_input)
return features.numpy()[0] # 768-dim
def embed_audio(self, audio_path: str) -> np.ndarray:
import whisper
model = whisper.load_model("base")
result = model.transcribe(audio_path, language="id") # Bahasa Indonesia
return self.embed_text(result["text"]) # audio → text → text embed
def _project_text(self, vec: np.ndarray) -> np.ndarray:
# Jika dimensi berbeda, project ke unified dim
# Untuk production: gunakan learned linear projection layer
if vec.shape[0] != self.unified_dim:
return vec[: self.unified_dim] # simple truncation — production pakai proper projection
return vec
# Indexing produk e-commerce
embedder = MultimodalEmbedder()
products = [
{"id": "p1", "name": "Kaos Polos Merah", "image": "p1.jpg"},
{"id": "p2", "name": "Kemeja Batik Pria", "image": "p2.jpg"},
]
for p in products:
text_vec = embedder.embed_text(p["name"])
image_vec = embedder.embed_image(p["image"])
# Combined embedding: average text + image
combined = (text_vec + image_vec) / 2
vector_db.store(p["id"], combined)
Cost Breakdown per Use Case
| Use Case | Komponen | Cost per 100k items | Waktu Setup |
|---|---|---|---|
| E-commerce image search (100k produk) | SigLIP self-hosted (RTX 3090, 1.7hr) + pgvector | ~$1.26 one-time + $0/query | 1–2 hari |
| Sama, pakai Cloudflare Workers AI | $0.011/1K images | ~$1.10 one-time + $0.011/1K update | Beberapa jam |
| Voice note search (100K menit audio) | Whisper API ($0.006/min) + text embed | ~$600 + $2 embed | 1 hari |
| Sama, pakai Whisper self-hosted | GPU compute (~20 menit A100) + embed | ~$0.83 compute + $2 embed | 1–2 hari (setup GPU) |
Untuk audio pipeline Indonesia, Whisper base/medium model memiliki akurasi yang sangat baik untuk Bahasa Indonesia — jauh lebih baik dari speech-to-text lain yang dioptimalkan untuk bahasa Inggris. Kalau volume audio tidak terlalu besar, Whisper API ($0.006/menit) adalah cara termudah tanpa perlu setup GPU sendiri.
Kesimpulan
Multimodal embedding bukan sesuatu yang hanya bisa dilakukan perusahaan besar — dengan kombinasi OSS model (SigLIP untuk gambar, multilingual-E5 untuk teks, Whisper untuk audio) dan vector DB seperti pgvector, pipeline ini bisa dibangun dalam 1–2 hari dengan biaya infrastruktur yang sangat rendah. Entry point terbaik: mulai dari satu modalitas (biasanya teks atau gambar), validasi use case, baru expand ke multimodal.