Bot WA AI dengan Image Recognition
Cara membuat bot AI WhatsApp dengan image recognition. Analisis foto, OCR, product identification. Tutorial lengkap!
Vision AI = Bot yang bisa "lihat"!
Bot dengan image recognition bisa analisis foto produk, baca teks dari gambar (OCR), verifikasi bukti transfer, dan banyak lagi.
Use Cases
📸 USE CASES IMAGE AI:
1. BUKTI TRANSFER
Customer kirim screenshot
→ Auto-verify pembayaran
2. PRODUCT IDENTIFICATION
Foto produk kompetitor
→ "Kami punya yang mirip!"
3. OCR (Text Extraction)
Foto KTP/dokumen
→ Extract data otomatis
4. DAMAGE REPORT
Foto produk rusak
→ Auto-assess untuk klaim
5. STYLE MATCHING
Foto outfit inspirasi
→ Rekomendasi produk mirip
6. RECEIPT SCANNING
Foto struk belanja
→ Input data otomatisImplementation dengan GPT-4 Vision
Basic Image Analysis:
javascript
const OpenAI = require('openai');
const openai = new OpenAI();
async function analyzeImage(imageUrl, prompt) {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: prompt
},
{
type: 'image_url',
image_url: {
url: imageUrl,
detail: 'high' // atau 'low' untuk hemat token
}
}
]
}
],
max_tokens: 1000
});
return response.choices[0].message.content;
}
// Dengan base64 (untuk gambar dari WhatsApp)
async function analyzeImageBase64(base64Data, mimeType, prompt) {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: prompt },
{
type: 'image_url',
image_url: {
url: `data:${mimeType};base64,${base64Data}`
}
}
]
}
]
});
return response.choices[0].message.content;
}WhatsApp Integration:
javascript
async function handleImageMessage(userId, message) {
const imageInfo = message.imageMessage || message.image;
// 1. Download image
const imageBuffer = await downloadMedia(imageInfo.id);
const base64 = imageBuffer.toString('base64');
const mimeType = imageInfo.mimetype || 'image/jpeg';
// 2. Get caption/context if any
const caption = imageInfo.caption || '';
// 3. Determine analysis type
const analysisType = detectAnalysisType(caption);
// 4. Analyze based on type
let result;
switch (analysisType) {
case 'payment_proof':
result = await verifyPaymentProof(base64, mimeType);
break;
case 'product_search':
result = await findSimilarProducts(base64, mimeType);
break;
case 'damage_report':
result = await assessDamage(base64, mimeType);
break;
default:
result = await generalImageAnalysis(base64, mimeType, caption);
}
return result;
}
function detectAnalysisType(caption) {
const lowerCaption = caption.toLowerCase();
if (lowerCaption.includes('bukti') || lowerCaption.includes('transfer')) {
return 'payment_proof';
}
if (lowerCaption.includes('cari') || lowerCaption.includes('mirip')) {
return 'product_search';
}
if (lowerCaption.includes('rusak') || lowerCaption.includes('cacat')) {
return 'damage_report';
}
return 'general';
}Verifikasi Bukti Transfer
javascript
async function verifyPaymentProof(base64, mimeType) {
const prompt = `Analisis screenshot bukti transfer ini.
Extract informasi berikut dalam format JSON:
{
"bank_pengirim": "nama bank",
"bank_tujuan": "nama bank",
"nominal": "jumlah dalam angka",
"tanggal": "tanggal transfer",
"jam": "jam transfer",
"no_referensi": "nomor referensi jika ada",
"nama_pengirim": "nama pengirim",
"nama_penerima": "nama penerima",
"is_valid": true/false,
"confidence": "high/medium/low",
"notes": "catatan jika ada yang mencurigakan"
}
Perhatikan tanda-tanda screenshot palsu seperti:
- Font tidak konsisten
- Angka tidak sejajar
- Watermark aneh
- Format tidak sesuai bank`;
const analysis = await analyzeImageBase64(base64, mimeType, prompt);
try {
const data = JSON.parse(analysis);
// Verify against pending orders
if (data.is_valid && data.confidence !== 'low') {
const matchedOrder = await findMatchingOrder(data.nominal);
if (matchedOrder) {
await updateOrderPayment(matchedOrder.id, {
verified: true,
proofData: data
});
return `✅ Pembayaran terverifikasi!
📋 Detail:
- Nominal: Rp ${parseInt(data.nominal).toLocaleString()}
- Order: #${matchedOrder.orderId}
- Bank: ${data.bank_pengirim}
Pesanan akan segera diproses! 🎉`;
}
}
return `⚠️ Tidak dapat memverifikasi otomatis.
Tim kami akan cek manual dalam 1x24 jam.
Atau hubungi CS untuk verifikasi lebih cepat.`;
} catch (e) {
return 'Maaf, gambar kurang jelas. Bisa kirim ulang dengan kualitas lebih baik?';
}
}Product Search by Image
javascript
async function findSimilarProducts(base64, mimeType) {
// 1. Analyze image to get product attributes
const analysisPrompt = `Analisis gambar produk fashion ini.
Identifikasi:
{
"category": "dress/blouse/pants/etc",
"style": "casual/formal/sporty/etc",
"colors": ["warna utama", "warna sekunder"],
"pattern": "polos/motif/stripes/etc",
"material_guess": "katun/silk/polyester/etc",
"occasion": ["casual", "kerja", "pesta"],
"keywords": ["keyword1", "keyword2"]
}`;
const analysis = await analyzeImageBase64(base64, mimeType, analysisPrompt);
const attributes = JSON.parse(analysis);
// 2. Search similar products in catalog
const similarProducts = await db.products.find({
category: attributes.category,
$or: [
{ colors: { $in: attributes.colors } },
{ tags: { $in: attributes.keywords } },
{ occasions: { $in: attributes.occasion } }
]
}).limit(5).toArray();
// 3. Format response
if (similarProducts.length > 0) {
let response = `Aku temukan produk mirip di katalog kami! 😊\n\n`;
similarProducts.forEach((p, i) => {
response += `${i+1}️⃣ *${p.name}*\n`;
response += ` 💰 Rp ${p.price.toLocaleString()}\n`;
response += ` 🎨 ${p.colors.join(', ')}\n\n`;
});
response += `Mau lihat detail yang mana kak?`;
return response;
}
return `Hmm, belum ada yang persis sama di katalog kami 😔
Tapi aku bisa carikan yang mirip stylenya!
Prefer warna apa kak?`;
}OCR untuk Dokumen
javascript
async function extractTextFromImage(base64, mimeType, documentType) {
const prompts = {
ktp: `Extract data dari foto KTP ini:
{
"nik": "16 digit",
"nama": "nama lengkap",
"tempat_lahir": "kota",
"tanggal_lahir": "DD-MM-YYYY",
"jenis_kelamin": "L/P",
"alamat": "alamat lengkap",
"rt_rw": "RT/RW",
"kelurahan": "nama",
"kecamatan": "nama",
"agama": "agama",
"status_perkawinan": "status",
"pekerjaan": "pekerjaan",
"kewarganegaraan": "WNI/WNA"
}`,
receipt: `Extract data dari struk/receipt ini:
{
"store_name": "nama toko",
"date": "tanggal",
"items": [{"name": "item", "qty": 1, "price": 0}],
"subtotal": 0,
"tax": 0,
"total": 0,
"payment_method": "cash/card/etc"
}`,
invoice: `Extract data dari invoice ini:
{
"invoice_number": "nomor",
"date": "tanggal",
"due_date": "jatuh tempo",
"vendor": "nama vendor",
"items": [{"description": "item", "qty": 1, "price": 0}],
"subtotal": 0,
"tax": 0,
"total": 0
}`
};
const prompt = prompts[documentType] ||
'Extract semua teks yang terlihat dari gambar ini.';
const result = await analyzeImageBase64(base64, mimeType, prompt);
return result;
}Damage Assessment
javascript
async function assessDamage(base64, mimeType) {
const prompt = `Analisis foto produk yang dilaporkan rusak/cacat.
Berikan assessment:
{
"damage_type": "jenis kerusakan",
"severity": "minor/moderate/severe",
"description": "deskripsi detail kerusakan",
"likely_cause": "kemungkinan penyebab",
"is_manufacturing_defect": true/false,
"is_shipping_damage": true/false,
"recommendation": "refund/replace/repair/reject",
"confidence": "high/medium/low",
"notes": "catatan tambahan"
}
Pertimbangkan:
- Apakah kerusakan wajar terjadi saat pengiriman?
- Apakah terlihat seperti defect produksi?
- Apakah terlihat seperti kerusakan akibat pemakaian?`;
const analysis = await analyzeImageBase64(base64, mimeType, prompt);
const data = JSON.parse(analysis);
// Auto-process based on assessment
if (data.confidence === 'high') {
if (data.recommendation === 'refund' || data.recommendation === 'replace') {
return `Terima kasih sudah kirim fotonya kak 🙏
📋 Assessment:
- Jenis: ${data.damage_type}
- Tingkat: ${data.severity}
- Deskripsi: ${data.description}
✅ Kami setujui pengajuan ${data.recommendation === 'refund' ? 'refund' : 'tukar baru'}.
Langkah selanjutnya:
1. Kami akan kirim label retur
2. Kirim balik produknya
3. ${data.recommendation === 'refund' ? 'Refund diproses 3-5 hari' : 'Produk baru dikirim'}
Ada pertanyaan kak?`;
}
}
return `Terima kasih fotonya kak!
Kami perlu review lebih lanjut oleh tim QC.
Estimasi: 1x24 jam.
Kami akan kabari hasilnya ya 🙏`;
}Multiple Image Analysis
javascript
async function analyzeMultipleImages(images, context) {
const content = [
{ type: 'text', text: context }
];
for (const img of images) {
content.push({
type: 'image_url',
image_url: {
url: `data:${img.mimeType};base64,${img.base64}`,
detail: 'low' // Use low for multiple images to save tokens
}
});
}
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content }],
max_tokens: 2000
});
return response.choices[0].message.content;
}
// Usage: Compare before/after
async function compareBeforeAfter(beforeImg, afterImg) {
return await analyzeMultipleImages(
[beforeImg, afterImg],
`Bandingkan kedua foto ini (before dan after).
Gambar 1: Kondisi sebelum
Gambar 2: Kondisi sesudah
Analisis:
1. Apa perbedaan yang terlihat?
2. Apakah ada perbaikan atau kerusakan?
3. Berikan rating perubahan 1-10`
);
}Cost Optimization
💰 VISION API PRICING:
GPT-4o Vision:
- Low detail: ~85 tokens per image
- High detail: 85-1700 tokens (depends on size)
TIPS HEMAT:
- Use 'low' detail untuk screening
- Resize image sebelum upload
- Cache hasil analysis
- Batch similar requests
EXAMPLE:
- 1000 images/day @ low detail
- ~85K tokens = ~$0.25/dayBest Practices
DO ✅
- Validate image before processing
- Use appropriate detail level
- Handle unclear images gracefully
- Confirm critical extractions
- Cache common analysis
- Compress imagesDON'T ❌
- Process without validation
- Always use high detail
- Trust 100% tanpa verify
- Skip error handling
- Unlimited image size
- No rate limitingFAQ
Accuracy OCR seberapa bagus?
GPT-4V: 90-95% untuk teks jelas. Kurang bagus untuk tulisan tangan atau blur.
Bisa detect fake screenshots?
Cukup bagus untuk yang obvious. Untuk yang sophisticated, perlu verification tambahan.
Kesimpulan
Vision AI = Bot yang lebih capable!
| Text Only | Vision + Text |
|---|---|
| Limited input | Rich input |
| Manual verify | Auto verify |
| No product search | Visual search |