N8n: ollama + n8n + telegram

From OnnoWiki
Jump to navigation Jump to search

Siap! Ini resep ringkas biar **Telegram ↔ n8n ↔ Ollama** bisa ngobrol dua arah.

  1. 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. 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

  1. Tarik model (contoh: Llama 3)

docker exec -it ollama ollama pull llama3

  1. atau model lain:
  2. docker exec -it ollama ollama pull llama3.1:8b-instruct
  3. docker exec -it ollama ollama pull qwen2.5:7b-instruct

```

Cek Ollama:

```bash curl http://localhost:11434/api/tags ```

---

    1. 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).

---

    1. 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.

---

    1. 4) Workflow n8n (Telegram → Ollama → Telegram)

Pakai 3 node:

      1. A. Node: Telegram Trigger
  • **Mode**: Polling
  • **Updates**: `message`
  • **Credentials**: pilih kredensial bot yang tadi dibuat
      1. B. Node: HTTP Request (ke Ollama)
 (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 > } > ```

      1. 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.

---

    1. 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.

---

    1. 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.

---

    1. 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?