N8n: ollama + n8n + telegram
Siap! Ini resep ringkas biar **Telegram ↔ n8n ↔ Ollama** bisa ngobrol dua arah.
- Arsitektur singkat
Telegram (user) ⇄ **n8n** (workflow) ⇄ **Ollama** (REST API /api/chat)
- **Telegram**: bot untuk terima & kirim pesan.
- **n8n**: ambil pesan Telegram → kirim ke Ollama → balikan jawaban ke Telegram.
- **Ollama**: jalankan model lokal (mis. `llama3`, `llama3.1:8b-instruct`, `qwen2.5`).
---
- 1) Jalankan service (Docker Compose)
Bikin file `docker-compose.yml`:
```yaml services:
ollama: image: ollama/ollama:latest container_name: ollama ports: - "11434:11434" volumes: - ollama_models:/root/.ollama restart: unless-stopped
n8n: image: n8nio/n8n:latest container_name: n8n ports: - "5678:5678" environment: - N8N_SECURE_COOKIE=false - N8N_DIAGNOSTICS_ENABLED=false # Jika akses dari LAN: set webhooks agar Telegram bisa call (opsional krn kita pakai polling) # - WEBHOOK_URL=https://n8n.yourdomain.com/ volumes: - n8n_data:/home/node/.n8n depends_on: - ollama restart: unless-stopped
volumes:
ollama_models: n8n_data:
```
Jalankan:
```bash docker compose up -d
- Tarik model (contoh: Llama 3)
docker exec -it ollama ollama pull llama3
- atau model lain:
- docker exec -it ollama ollama pull llama3.1:8b-instruct
- docker exec -it ollama ollama pull qwen2.5:7b-instruct
```
Cek Ollama:
```bash curl http://localhost:11434/api/tags ```
---
- 2) Buat bot Telegram
1. Chat ke **@BotFather** → `/newbot` 2. Kasih nama & username unik → dapat **Bot Token** (format `123456:ABC-...`) 3. Catat token ini (dipakai di n8n).
> Untuk mode praktis/offline-friendly kita pakai **polling** (tidak perlu webhook/HTTPS).
---
- 3) Siapkan kredensial Telegram di n8n
1. Buka n8n di `http://localhost:5678` 2. **Credentials → New → Telegram** (pilih *Telegram Bot API*) 3. Isi **Bot Token** dari BotFather → Save.
---
- 4) Workflow n8n (Telegram → Ollama → Telegram)
Pakai 3 node:
- **Telegram Trigger** (poll “new messages”)
- **HTTP Request** (POST ke `http://ollama:11434/api/chat`)
- **Telegram** (send message reply)
- A. Node: Telegram Trigger
- **Mode**: Polling
- **Updates**: `message`
- **Credentials**: pilih kredensial bot yang tadi dibuat
- B. Node: HTTP Request (ke Ollama)
- **Method**: POST
- **URL**: `http://ollama:11434/api/chat`
(pakai `ollama` karena satu jaringan Docker; jika n8n di host lain: `http://host.docker.internal:11434/api/chat` atau IP-nya)
- **Send Body**: JSON
- **JSON/Body** (ganti model sesuai yang dipull):
```json {
"model": "llama3", "stream": false, "messages": [ { "role": "system", "content": "Kamu adalah asisten ramah yang menjawab ringkas dan akurat dalam Bahasa Indonesia." }, { "role": "user", "content": "={{$json[\"message\"][\"text\"]}}" } ]
} ```
- **Response**: JSON
> Respons Ollama (non-stream) bentuknya: > > ```json > { > "model": "llama3", > "message": { "role": "assistant", "content": "..." }, > "done": true > } > ```
- C. Node: Telegram (Send)
- **Chat ID**: `={{$json["message"]["chat"]["id"]}}` (ambil dari output *Telegram Trigger*)
- **Text**:
``` ={{$node["HTTP Request"].json["message"]["content"]}} ```
Sambungkan alur: **Telegram Trigger → HTTP Request → Telegram** Aktifkan workflow (toggle **Active** / Run once untuk uji coba). Kirim chat ke bot Anda di Telegram—harusnya bot balas jawaban dari Ollama.
---
- 5) (Opsional) Batasi panjang & “typing…” effect
Telegram punya limit panjang pesan. Untuk aman, tambahkan **Function** node di antara HTTP Request → Telegram:
- Function (Split)**:
```js // input: $node["HTTP Request"].json.message.content const text = $node["HTTP Request"].json.message.content || ""; const chunkSize = 3500; const chunks = [];
for (let i = 0; i < text.length; i += chunkSize) {
chunks.push({ chunk: text.slice(i, i + chunkSize) });
}
return chunks.map(c => ({ json: c })); ```
Lalu pakai **Split In Batches** → **Telegram** (Send) dengan Text:
``` ={{$json["chunk"]}} ```
Hasilnya dikirim bertahap kalau jawaban panjang.
---
- 6) Contoh workflow JSON (siap import ke n8n)
Simpan sebagai `telegram_ollama.json` lalu **Import** di n8n:
```json {
"name": "Telegram ↔ Ollama Chat", "nodes": [ { "parameters": { "updates": "message", "additionalFields": {} }, "id": "TelegramTrigger", "name": "Telegram Trigger", "type": "n8n-nodes-base.telegramTrigger", "typeVersion": 1, "position": [200, 300], "credentials": { "telegramApi": { "id": "__REPLACE_WITH_YOUR_CREDENTIAL_ID__", "name": "__REPLACE_WITH_YOUR_CREDENTIAL_NAME__" } } }, { "parameters": { "url": "http://ollama:11434/api/chat", "options": {}, "jsonParameters": true, "sendBody": true, "bodyParametersJson": "={\n \"model\": \"llama3\",\n \"stream\": false,\n \"messages\": [\n { \"role\": \"system\", \"content\": \"Kamu adalah asisten ramah yang menjawab ringkas dan akurat dalam Bahasa Indonesia.\" },\n { \"role\": \"user\", \"content\": $json[\"message\"][\"text\"] }\n ]\n}" }, "id": "OllamaChat", "name": "HTTP Request", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4, "position": [520, 300] }, { "parameters": { "chatId": "={{$json[\"message\"][\"chat\"][\"id\"]}}", "text": "={{$node[\"HTTP Request\"].json[\"message\"][\"content\"]}}" }, "id": "TelegramSend", "name": "Telegram (Send)", "type": "n8n-nodes-base.telegram", "typeVersion": 1, "position": [840, 300], "credentials": { "telegramApi": { "id": "__REPLACE_WITH_YOUR_CREDENTIAL_ID__", "name": "__REPLACE_WITH_YOUR_CREDENTIAL_NAME__" } } } ], "connections": { "Telegram Trigger": { "main": [ [{ "node": "HTTP Request", "type": "main", "index": 0 }] ] }, "HTTP Request": { "main": [ [{ "node": "Telegram (Send)", "type": "main", "index": 0 }] ] } }
} ```
> Setelah import, buka tiap node dan pilih kredensial Telegram Anda.
---
- 7) Tips & variasi
- **Model**: ganti `"model": "llama3"` ke apa pun yang sudah di-pull (mis. `"llama3.1:8b-instruct"`, `"qwen2.5:7b-instruct"`).
- **Konteks khusus**: tambahkan *system prompt* (mis. jawaban singkat, gunakan bullet, dll).
- **RAG lokal**: sebelum call Ollama, tambahkan node yang ambil dokumen (filesystem/URL), rangkum, lalu sisipkan ke `messages` sebagai `role: "system"` atau `role: "user"` (context).
- **Keamanan**: kalau n8n diekspos publik, lindungi dengan reverse proxy + HTTPS (Caddy/Traefik) dan batasi akses bot (mis. cek `from.id` lalu tolak user yang tidak dikenali).
- **Non-stream**: n8n lebih mudah dengan `stream: false`. Kalau ingin efek streaming, butuh custom node/Function untuk konsumsi SSE; untuk workflow pemula, hindari dulu.
---
Kalau mau, saya bisa kasih variasi workflow yang **multi-turn memory** (menyimpan riwayat per chat id) atau **mode perintah** (prefix `/summarize`, `/translate`, dll). Mau lanjut ke versi itu?