Saltar al contenido principal

Cómo Conectar WhatsApp con Ollama (IA Local) Cómo Conectar WhatsApp con Ollama (IA Local)

Cómo Conectar WhatsApp con Ollama (IA Local)

Ejecuta tu chatbot de WhatsApp completamente en tu propia máquina — sin API keys, sin costos de nube, sin datos saliendo de tu red. Ollama facilita ejecutar modelos open source como Llama, Gemma y Mistral localmente.

Requisitos Previos

  • Una sesión vinculada de whatsmeow-node (Cómo Vincular)
  • Ollama instalado y corriendo
  • Un modelo descargado: ollama pull llama3.2
  • El SDK de Ollama: npm install ollama

Paso 1: Descargar un Modelo

# Install Ollama from https://ollama.com, then:
ollama pull llama3.2

Otras buenas opciones para chat:

  • gemma3 — modelo abierto de Google, rápido y capaz
  • mistral — potente para su tamaño
  • llama3.2:1b — el Llama más pequeño, respuestas más rápidas

Paso 2: Configurar Ambos Clientes

import { createClient } from "@whatsmeow-node/whatsmeow-node";
import { Ollama } from "ollama";

const client = createClient({ store: "session.db" });
const ollama = new Ollama({ host: "http://localhost:11434" });

const MODEL = "llama3.2";
const SYSTEM_PROMPT = "You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";

Paso 3: Manejar Mensajes Entrantes

client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;

const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;

await client.sendChatPresence(info.chat, "composing");

const reply = await askOllama(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
});

Paso 4: Enviar a Ollama

async function askOllama(userJid: string, userMessage: string): Promise<string> {
const response = await ollama.chat({
model: MODEL,
messages: [
{ role: "system", content: SYSTEM_PROMPT },
{ role: "user", content: userMessage },
],
});

return response.message.content;
}

Paso 5: Agregar Historial de Conversación

import type { Message } from "ollama";

const conversations = new Map<string, Message[]>();
const MAX_HISTORY = 20;

async function askOllama(userJid: string, userMessage: string): Promise<string> {
const history = conversations.get(userJid) ?? [];
history.push({ role: "user", content: userMessage });

if (history.length > MAX_HISTORY) {
history.splice(0, history.length - MAX_HISTORY);
}

const response = await ollama.chat({
model: MODEL,
messages: [{ role: "system", content: SYSTEM_PROMPT }, ...history],
});

const reply = response.message.content;
history.push({ role: "assistant", content: reply });
conversations.set(userJid, history);

return reply;
}

Ejemplo Completo

import { createClient } from "@whatsmeow-node/whatsmeow-node";
import { Ollama } from "ollama";
import type { Message } from "ollama";

const client = createClient({ store: "session.db" });
const ollama = new Ollama({ host: "http://localhost:11434" });

const MODEL = "llama3.2";
const SYSTEM_PROMPT =
"You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";

const conversations = new Map<string, Message[]>();
const MAX_HISTORY = 20;

async function askOllama(userJid: string, userMessage: string): Promise<string> {
const history = conversations.get(userJid) ?? [];
history.push({ role: "user", content: userMessage });

if (history.length > MAX_HISTORY) {
history.splice(0, history.length - MAX_HISTORY);
}

const response = await ollama.chat({
model: MODEL,
messages: [{ role: "system", content: SYSTEM_PROMPT }, ...history],
});

const reply = response.message.content;
history.push({ role: "assistant", content: reply });
conversations.set(userJid, history);

return reply;
}

client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;

const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;

console.log(`${info.pushName}: ${text}`);
await client.sendChatPresence(info.chat, "composing");

try {
const reply = await askOllama(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
console.log(`${reply.slice(0, 80)}...`);
} catch (err) {
console.error("Ollama error:", err);
await client.sendMessage(info.chat, {
conversation: "Sorry, I'm having trouble right now. Make sure Ollama is running.",
});
}
});

client.on("logged_out", ({ reason }) => {
console.error(`Logged out: ${reason}`);
client.close();
process.exit(1);
});

async function main() {
const { jid } = await client.init();
if (!jid) {
console.error("Not paired! See: How to Pair WhatsApp");
process.exit(1);
}
await client.connect();
await client.sendPresence("available");
console.log(`Ollama bot is online! (model: ${MODEL})`);

process.on("SIGINT", async () => {
await client.sendPresence("unavailable");
await client.disconnect();
client.close();
process.exit(0);
});
}

main().catch(console.error);

Errores Comunes

Ollama debe estar corriendo

Asegúrate de que el servidor de Ollama esté corriendo (ollama serve) antes de iniciar el bot. Si no está corriendo, todas las peticiones van a fallar.

El tiempo de respuesta depende del hardware

Los modelos locales corren en tu CPU/GPU. Modelos más pequeños como llama3.2:1b responden en 1-3 segundos en hardware moderno. Modelos más grandes pueden tardar 10+ segundos — el indicador de escritura mantiene informado al usuario mientras espera.

Bucles de eco

Siempre verifica info.isFromMe primero. Sin esto, el bot responde a sus propios mensajes para siempre.

El modelo debe estar descargado primero

Ejecuta ollama pull llama3.2 antes de iniciar el bot. Si el modelo no está descargado, las peticiones van a fallar.