55 6 months ago

Asisten AI untuk customer service & marketing yang dikembangkan untuk ChatBot di berbagai Platform

tools

Models

View all →

Readme

Tutorial: Membuat Telegram Bot dengan ExaBot-Micro (Ollama API) [HANYA CONTOH]

πŸ€– Overview

Tutorial ini akan memandu Anda membuat chatbot Telegram menggunakan model AI ExaBot-Micro melalui API Ollama. ExaBot-Micro adalah model AI yang dioptimasi untuk customer service & marketing dengan ukuran hanya 1.3 GB.

πŸ“‹ Prerequisites

  • Python 3.8+
  • Ollama terinstall dan running
  • Model ExaBot-Micro sudah tersedia di Ollama
  • Telegram Bot Token (dari @BotFather)

πŸš€ Langkah 1: Setup Environment

1.1 Install Dependencies

# Install required packages
pip install python-telegram-bot requests aiohttp python-dotenv

# Alternative menggunakan requirements.txt
pip install -r requirements.txt

1.2 Buat File requirements.txt

python-telegram-bot==20.7
requests==2.31.0
aiohttp==3.9.1
python-dotenv==1.0.0

1.3 Setup Environment Variables (.env)

# Telegram Bot Configuration
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here

# Ollama Configuration
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL_NAME=exabot-micro

# Optional: Advanced Settings
MAX_MESSAGE_LENGTH=4000
TIMEOUT_SECONDS=30

πŸ”§ Langkah 2: Verifikasi Setup Ollama

2.1 Test Ollama API

# Test apakah Ollama berjalan
curl http://localhost:11434/api/version

# Test model ExaBot-Micro
curl -X POST http://localhost:11434/api/generate \
  -H "Content-Type: application/json" \
  -d '{
    "model": "exabot-micro",
    "prompt": "Halo, siapa kamu?",
    "stream": false
  }'

2.2 Setup Model ExaBot-Micro (Jika Belum Ada)

# Jika belum ada, buat model ExaBot-Micro
ollama create exabot-micro -f Modelfile-micro

# Test model
ollama run exabot-micro "Halo, perkenalkan dirimu"

πŸ€– Langkah 3: Membuat Telegram Bot

3.1 Dapatkan Bot Token

  1. Chat dengan @BotFather di Telegram
  2. Ketik /newbot
  3. Berikan nama bot: ExaBot Customer Service
  4. Berikan username: @exabot_cs_bot (harus unik)
  5. Simpan token yang diberikan

3.2 Basic Bot Code (telegram_bot.py)

import os
import asyncio
import logging
from dotenv import load_dotenv
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
import requests
import json

# Load environment variables
load_dotenv()

# Setup logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

class ExaBotTelegram:
    def __init__(self):
        self.bot_token = os.getenv('TELEGRAM_BOT_TOKEN')
        self.ollama_url = os.getenv('OLLAMA_BASE_URL', 'http://localhost:11434')
        self.model_name = os.getenv('OLLAMA_MODEL_NAME', 'exabot-micro')
        self.max_length = int(os.getenv('MAX_MESSAGE_LENGTH', '4000'))
        self.timeout = int(os.getenv('TIMEOUT_SECONDS', '30'))
        
    async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Handler untuk command /start"""
        welcome_message = """
πŸ€– **Selamat datang di ExaBot!**

Saya adalah asisten AI yang dikembangkan oleh Saputra Budi untuk membantu customer service & marketing.

**Commands yang tersedia:**
β€’ /start - Menampilkan pesan ini
β€’ /help - Bantuan penggunaan
β€’ /info - Informasi tentang bot
β€’ Atau langsung chat dengan saya!

**Contoh pertanyaan:**
β€’ "Apa produk unggulan Anda?"
β€’ "Bagaimana cara melakukan pemesanan?"
β€’ "Berapa harga produk X?"

Mari mulai percakapan! πŸ’¬
        """
        await update.message.reply_text(welcome_message, parse_mode='Markdown')

    async def help_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Handler untuk command /help"""
        help_text = """
πŸ“– **Bantuan ExaBot**

**Cara menggunakan:**
1. Ketik pertanyaan Anda dalam bahasa Indonesia
2. Tunggu respons dari ExaBot
3. Lanjutkan percakapan sesuai kebutuhan

**Tips:**
β€’ Gunakan bahasa yang jelas dan spesifik
β€’ Bot ini dioptimasi untuk customer service & marketing
β€’ Respons akan singkat dan to-the-point

**Masalah teknis?**
Contact: @saputrabudi
        """
        await update.message.reply_text(help_text, parse_mode='Markdown')

    async def info_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Handler untuk command /info"""
        info_text = """
ℹ️ **Informasi ExaBot**

**Model:** ExaBot-Micro v1.0
**Developer:** Saputra Budi
**Engine:** Ollama + Llama 3.2:1b
**Ukuran Model:** 1.3 GB
**Optimized untuk:** Customer Service & Marketing Indonesia

**Kemampuan:**
βœ… Jawaban singkat dan akurat
βœ… Bahasa Indonesia natural
βœ… Response time cepat
βœ… Context-aware conversation

**Powered by Ollama API**
        """
        await update.message.reply_text(info_text, parse_mode='Markdown')

    def query_ollama(self, prompt: str) -> str:
        """Send query to Ollama API and get response"""
        try:
            payload = {
                "model": self.model_name,
                "prompt": prompt,
                "stream": False,
                "options": {
                    "temperature": 0.5,
                    "num_predict": 500,
                    "num_ctx": 1024
                }
            }
            
            response = requests.post(
                f"{self.ollama_url}/api/generate",
                json=payload,
                timeout=self.timeout
            )
            
            if response.status_code == 200:
                result = response.json()
                return result.get('response', 'Maaf, tidak ada respons dari model.')
            else:
                logger.error(f"Ollama API error: {response.status_code}")
                return "❌ Maaf, terjadi kesalahan pada sistem AI."
                
        except requests.exceptions.Timeout:
            logger.error("Ollama API timeout")
            return "⏱️ Timeout - Mohon coba lagi dalam beberapa saat."
        except requests.exceptions.ConnectionError:
            logger.error("Cannot connect to Ollama API")
            return "πŸ”Œ Tidak dapat terhubung ke AI service. Admin telah diberitahu."
        except Exception as e:
            logger.error(f"Unexpected error: {str(e)}")
            return "❌ Terjadi kesalahan tidak terduga. Mohon coba lagi."

    async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Handler untuk semua pesan text"""
        user_message = update.message.text
        user_name = update.message.from_user.first_name or "User"
        
        # Log incoming message
        logger.info(f"Message from {user_name}: {user_message}")
        
        # Show typing indicator
        await context.bot.send_chat_action(
            chat_id=update.effective_chat.id, 
            action='typing'
        )
        
        # Get AI response
        ai_response = self.query_ollama(user_message)
        
        # Truncate if too long
        if len(ai_response) > self.max_length:
            ai_response = ai_response[:self.max_length] + "..."
            
        # Send response
        await update.message.reply_text(ai_response)
        
        # Log response
        logger.info(f"Response sent to {user_name}: {ai_response[:100]}...")

    async def error_handler(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Log errors caused by updates"""
        logger.warning(f'Update "{update}" caused error "{context.error}"')

    def run(self):
        """Start the bot"""
        if not self.bot_token:
            logger.error("TELEGRAM_BOT_TOKEN not found in environment variables")
            return
            
        # Create application
        application = Application.builder().token(self.bot_token).build()
        
        # Add handlers
        application.add_handler(CommandHandler("start", self.start_command))
        application.add_handler(CommandHandler("help", self.help_command))
        application.add_handler(CommandHandler("info", self.info_command))
        application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, self.handle_message))
        application.add_error_handler(self.error_handler)
        
        # Start the bot
        logger.info("Starting ExaBot Telegram Bot...")
        print("πŸ€– ExaBot Telegram Bot is running...")
        print("Press Ctrl+C to stop")
        
        application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == '__main__':
    bot = ExaBotTelegram()
    bot.run()

πŸƒβ€β™‚οΈ Langkah 4: Menjalankan Bot

4.1 Setup File .env

# Buat file .env
nano .env

# Isi dengan:
TELEGRAM_BOT_TOKEN=1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL_NAME=exabot-micro
MAX_MESSAGE_LENGTH=4000
TIMEOUT_SECONDS=30

4.2 Jalankan Bot

# Pastikan Ollama running
ollama serve

# Di terminal lain, jalankan bot
python telegram_bot.py

4.3 Test Bot

  1. Cari bot Anda di Telegram: @exabot_cs_bot
  2. Klik Start atau ketik /start
  3. Coba chat: β€œHalo, siapa kamu?”
  4. Test commands: /help, /info

πŸ”§ Langkah 5: Advanced Features

5.1 Bot dengan Memory/Context (advanced_bot.py)

import sqlite3
from datetime import datetime, timedelta

class ExaBotWithMemory(ExaBotTelegram):
    def __init__(self):
        super().__init__()
        self.init_database()
    
    def init_database(self):
        """Initialize SQLite database for conversation history"""
        self.conn = sqlite3.connect('exabot_conversations.db', check_same_thread=False)
        self.conn.execute('''
            CREATE TABLE IF NOT EXISTS conversations (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                user_name TEXT,
                message TEXT,
                response TEXT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        self.conn.commit()
    
    def get_conversation_context(self, user_id: int, limit: int = 3) -> str:
        """Get recent conversation context for user"""
        cursor = self.conn.execute('''
            SELECT message, response FROM conversations 
            WHERE user_id = ? AND timestamp > datetime('now', '-1 hour')
            ORDER BY timestamp DESC LIMIT ?
        ''', (user_id, limit))
        
        context = ""
        for message, response in reversed(cursor.fetchall()):
            context += f"User: {message}\nExaBot: {response}\n\n"
        
        return context
    
    def save_conversation(self, user_id: int, user_name: str, message: str, response: str):
        """Save conversation to database"""
        self.conn.execute('''
            INSERT INTO conversations (user_id, user_name, message, response)
            VALUES (?, ?, ?, ?)
        ''', (user_id, user_name, message, response))
        self.conn.commit()
    
    def query_ollama_with_context(self, prompt: str, user_id: int) -> str:
        """Send query with conversation context"""
        try:
            # Get conversation context
            context = self.get_conversation_context(user_id)
            
            # Build enhanced prompt
            enhanced_prompt = f"""Context percakapan sebelumnya:
{context}

Pertanyaan terbaru: {prompt}

Jawab dengan mempertimbangkan context percakapan sebelumnya jika relevan."""

            payload = {
                "model": self.model_name,
                "prompt": enhanced_prompt,
                "stream": False,
                "options": {
                    "temperature": 0.5,
                    "num_predict": 500,
                    "num_ctx": 2048  # Increased for context
                }
            }
            
            response = requests.post(
                f"{self.ollama_url}/api/generate",
                json=payload,
                timeout=self.timeout
            )
            
            if response.status_code == 200:
                result = response.json()
                return result.get('response', 'Maaf, tidak ada respons dari model.')
            else:
                logger.error(f"Ollama API error: {response.status_code}")
                return "❌ Maaf, terjadi kesalahan pada sistem AI."
                
        except Exception as e:
            logger.error(f"Error in context query: {str(e)}")
            return self.query_ollama(prompt)  # Fallback to basic query
    
    async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Enhanced message handler with context"""
        user_message = update.message.text
        user_id = update.message.from_user.id
        user_name = update.message.from_user.first_name or "User"
        
        logger.info(f"Message from {user_name} (ID: {user_id}): {user_message}")
        
        await context.bot.send_chat_action(
            chat_id=update.effective_chat.id, 
            action='typing'
        )
        
        # Get AI response with context
        ai_response = self.query_ollama_with_context(user_message, user_id)
        
        # Save conversation
        self.save_conversation(user_id, user_name, user_message, ai_response)
        
        if len(ai_response) > self.max_length:
            ai_response = ai_response[:self.max_length] + "..."
            
        await update.message.reply_text(ai_response)
        logger.info(f"Response sent to {user_name}: {ai_response[:100]}...")

5.2 Bot dengan Rate Limiting

from collections import defaultdict
import time

class ExaBotWithRateLimit(ExaBotTelegram):
    def __init__(self):
        super().__init__()
        self.user_requests = defaultdict(list)
        self.rate_limit = 10  # messages per minute
        self.rate_window = 60  # seconds
    
    def is_rate_limited(self, user_id: int) -> bool:
        """Check if user is rate limited"""
        now = time.time()
        user_times = self.user_requests[user_id]
        
        # Remove old requests outside the window
        user_times[:] = [t for t in user_times if now - t < self.rate_window]
        
        # Check if limit exceeded
        if len(user_times) >= self.rate_limit:
            return True
        
        # Add current request
        user_times.append(now)
        return False
    
    async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
        """Message handler with rate limiting"""
        user_id = update.message.from_user.id
        
        if self.is_rate_limited(user_id):
            await update.message.reply_text(
                "⏱️ Anda terlalu cepat mengirim pesan. Mohon tunggu sebentar."
            )
            return
        
        # Continue with normal processing
        await super().handle_message(update, context)

🐳 Langkah 6: Deployment dengan Docker

6.1 Dockerfile

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

# Create directory for database
RUN mkdir -p /app/data

# Run the bot
CMD ["python", "telegram_bot.py"]

6.2 Docker Compose (docker-compose.yml)

version: '3.8'

services:
  exabot-telegram:
    build: .
    environment:
      - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
      - OLLAMA_BASE_URL=http://ollama:11434
      - OLLAMA_MODEL_NAME=exabot-micro
    volumes:
      - ./data:/app/data
    depends_on:
      - ollama
    restart: unless-stopped

  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    environment:
      - OLLAMA_HOST=0.0.0.0
    restart: unless-stopped

volumes:
  ollama_data:

6.3 Deploy dengan Docker

# Build dan run
docker-compose up -d

# Setup model di container ollama
docker-compose exec ollama ollama pull llama3.2:1b
docker-compose exec ollama ollama create exabot-micro -f /path/to/Modelfile-micro

# Check logs
docker-compose logs -f exabot-telegram

πŸ” Troubleshooting

Problem 1: Bot tidak merespon

# Check Ollama service
curl http://localhost:11434/api/version

# Check model availability
ollama list | grep exabot-micro

# Check bot logs
tail -f telegram_bot.log

Problem 2: Timeout errors

# Increase timeout di .env
TIMEOUT_SECONDS=60

# Atau di code:
payload["options"]["timeout"] = 60

Problem 3: Memory usage tinggi

# Limit Ollama memory
OLLAMA_MAX_LOADED_MODELS=1 ollama serve

# Monitor usage
docker stats

Problem 4: Rate limiting dari Telegram

# Add delay between responses
import asyncio
await asyncio.sleep(1)

πŸ“Š Monitoring & Analytics

7.1 Basic Monitoring Script (monitor.py)

import sqlite3
from datetime import datetime, timedelta
import matplotlib.pyplot as plt

def generate_usage_report():
    """Generate bot usage report"""
    conn = sqlite3.connect('exabot_conversations.db')
    
    # Daily usage stats
    cursor = conn.execute('''
        SELECT DATE(timestamp) as date, COUNT(*) as messages
        FROM conversations 
        WHERE timestamp > datetime('now', '-7 days')
        GROUP BY DATE(timestamp)
        ORDER BY date
    ''')
    
    dates, counts = zip(*cursor.fetchall()) if cursor.fetchall() else ([], [])
    
    # Plot usage
    plt.figure(figsize=(10, 6))
    plt.plot(dates, counts, marker='o')
    plt.title('ExaBot Daily Usage (Last 7 Days)')
    plt.xlabel('Date')
    plt.ylabel('Messages')
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.savefig('usage_report.png')
    plt.show()
    
    # Top users
    cursor = conn.execute('''
        SELECT user_name, COUNT(*) as messages
        FROM conversations 
        WHERE timestamp > datetime('now', '-7 days')
        GROUP BY user_id, user_name
        ORDER BY messages DESC
        LIMIT 10
    ''')
    
    print("\nπŸ“Š Top Users (Last 7 Days):")
    for user, count in cursor.fetchall():
        print(f"β€’ {user}: {count} messages")
    
    conn.close()

if __name__ == '__main__':
    generate_usage_report()

πŸš€ Production Deployment Checklist

8.1 Security Checklist

  • [ ] Bot token disimpan di environment variables
  • [ ] Rate limiting diaktifkan
  • [ ] Input validation untuk user messages
  • [ ] Logging untuk security events
  • [ ] HTTPS untuk webhook (jika menggunakan webhook mode)

8.2 Performance Checklist

  • [ ] Connection pooling untuk database
  • [ ] Caching untuk frequent queries
  • [ ] Async processing untuk heavy operations
  • [ ] Resource monitoring setup
  • [ ] Auto-restart on failures

8.3 Deployment Script (deploy.sh)

#!/bin/bash

echo "πŸš€ Deploying ExaBot Telegram Bot..."

# Stop existing containers
docker-compose down

# Pull latest changes
git pull origin main

# Rebuild and start
docker-compose up -d --build

# Wait for services to start
sleep 10

# Test bot health
curl -f http://localhost:11434/api/version || exit 1

echo "βœ… ExaBot deployed successfully!"
echo "πŸ“Š Check status: docker-compose ps"
echo "πŸ“‹ View logs: docker-compose logs -f exabot-telegram"

πŸ“± Contoh Percakapan

User: /start
Bot: πŸ€– Selamat datang di ExaBot! Saya adalah asisten AI yang dikembangkan oleh Saputra Budi untuk membantu customer service & marketing...

User: Halo, siapa kamu?
Bot: Halo! Saya ExaBot, Asisten AI yang dikembangkan oleh Saputra Budi untuk customer service & marketing. Saya siap membantu Anda dengan pertanyaan seputar produk, layanan, atau informasi lainnya. Ada yang bisa saya bantu hari ini?

User: Apa produk unggulan kalian?
Bot: Sebagai asisten AI, saya dapat membantu menjelaskan berbagai produk unggulan yang tersedia. Namun untuk informasi spesifik tentang produk unggulan perusahaan tertentu, mohon berikan detail lebih lanjut tentang bisnis atau industri yang Anda maksud, sehingga saya dapat memberikan rekomendasi yang lebih tepat.

User: Bagaimana cara melakukan pemesanan?
Bot: Berikut cara umum melakukan pemesanan:

1. πŸ“ž **Kontak Langsung**: Hubungi customer service
2. 🌐 **Website**: Akses portal pemesanan online  
3. πŸ“± **Aplikasi**: Gunakan mobile app jika tersedia
4. πŸ’¬ **Chat**: Melalui live chat atau WhatsApp

Untuk pemesanan spesifik, mohon informasikan jenis produk/layanan yang ingin dipesan agar saya dapat memberikan panduan yang lebih detail.

🎯 Next Steps & Improvements

Fitur yang Bisa Ditambahkan:

  1. Multi-language support (English, Indonesian)
  2. Voice message processing (speech-to-text)
  3. Image analysis dengan vision models
  4. Integration dengan CRM systems
  5. Automated customer satisfaction surveys
  6. Smart escalation ke human agents
  7. Business analytics dashboard
  8. WhatsApp Business API integration

Performance Optimizations:

  1. Model caching untuk response lebih cepat
  2. Database optimization dengan indexing
  3. Load balancing untuk multiple instances
  4. CDN integration untuk static assets
  5. Background job processing untuk heavy tasks