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?