AI Setup & Configuration
This guide covers the complete setup process for KAIU’s AI-powered WhatsApp assistant, including environment variables, database configuration, and deployment.
Prerequisites
Node.js Version 18+ required for LangChain and Prisma
PostgreSQL Version 14+ with pgvector extension support
Redis For BullMQ queue management
Meta Business Account WhatsApp Business API access
Environment Variables
Create a .env file in the project root:
# Database
DATABASE_URL = "postgresql://user:password@localhost:5432/kaiu_db?schema=public"
# Redis (BullMQ)
REDIS_URL = "redis://localhost:6379" # Or use individual vars below
REDIS_HOST = "localhost"
REDIS_PORT = "6379"
REDIS_PASSWORD = "" # Optional
# Anthropic AI
ANTHROPIC_API_KEY = "sk-ant-api03-..." # Get from https://console.anthropic.com
# WhatsApp Business API
WHATSAPP_PHONE_ID = "123456789012345" # From Meta Business Manager
WHATSAPP_ACCESS_TOKEN = "EAAxxxx..." # Long-lived access token
WHATSAPP_VERIFY_TOKEN = "your_custom_verify_token" # For webhook verification
# Server
BASE_URL = "https://yourdomain.com" # For image URLs
PORT = "3001"
# SSL (Development only)
NODE_TLS_REJECT_UNAUTHORIZED = "0" # Set to "1" in production
Getting API Keys
Anthropic API Key
Sign up at console.anthropic.com
Navigate to API Keys
Create a new key
Copy and save securely (starts with sk-ant-api03-)
WhatsApp Business API
Create a Meta Business account
Set up WhatsApp Business API in Business Manager
Get WHATSAPP_PHONE_ID from Phone Numbers section
Generate a permanent access token (not the temporary 24h token)
Redis Connection
For local development: docker run -d -p 6379:6379 redis:7-alpine
For production, use managed services:
Database Setup
1. Enable pgvector Extension
CREATE EXTENSION IF NOT EXISTS vector ;
Ensure your PostgreSQL instance supports pgvector. Most managed services (Supabase, Neon, Railway) include it by default.
2. Run Prisma Migrations
# Install dependencies
npm install
# Generate Prisma client
npx prisma generate
# Run migrations
npx prisma migrate deploy
3. Verify Tables
-- Check if tables exist
SELECT tablename FROM pg_tables WHERE schemaname = 'public' ;
-- Should include:
-- ✓ users
-- ✓ products
-- ✓ orders
-- ✓ order_items
-- ✓ addresses
-- ✓ knowledge_base
-- ✓ whatsapp_sessions
4. Create Vector Index
-- For fast similarity search (recommended for 1K+ documents)
CREATE INDEX IF NOT EXISTS knowledge_base_embedding_idx
ON knowledge_base
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100 );
Installation
Clone and Install
# Clone repository
git clone https://github.com/your-org/kaiu-backend.git
cd kaiu-backend
# Install dependencies
npm install
# Setup environment
cp .env.example .env
# Edit .env with your values
Required Packages
The AI system uses these core dependencies:
{
"dependencies" : {
"@langchain/anthropic" : "^0.1.0" ,
"@langchain/core" : "^0.1.0" ,
"@prisma/client" : "^5.0.0" ,
"bullmq" : "^4.0.0" ,
"ioredis" : "^5.3.0" ,
"axios" : "^1.6.0" ,
"socket.io" : "^4.6.0"
},
"devDependencies" : {
"prisma" : "^5.0.0"
}
}
Running the System
Development Mode
# Terminal 1: Start the main server
npm run dev
# Terminal 2: Start the queue worker (if separate)
node backend/whatsapp/queue.js
Production Mode
# Build
npm run build
# Start with PM2
pm2 start ecosystem.config.js
PM2 Configuration
Create ecosystem.config.js:
module . exports = {
apps: [
{
name: 'kaiu-api' ,
script: './backend/server.js' ,
instances: 2 ,
exec_mode: 'cluster' ,
env: {
NODE_ENV: 'production' ,
PORT: 3001
}
},
{
name: 'kaiu-worker' ,
script: './backend/whatsapp/queue.js' ,
instances: 1 ,
env: {
NODE_ENV: 'production'
}
}
]
};
WhatsApp Webhook Setup
In Meta Business Manager:
Go to WhatsApp > Configuration
Set Webhook URL: https://yourdomain.com/webhook/whatsapp
Set Verify Token: (matches WHATSAPP_VERIFY_TOKEN in .env)
Subscribe to events: messages
2. Verify Webhook
Meta will send a GET request to verify:
// backend/webhook/whatsapp.js
app . get ( '/webhook/whatsapp' , ( req , res ) => {
const mode = req . query [ 'hub.mode' ];
const token = req . query [ 'hub.verify_token' ];
const challenge = req . query [ 'hub.challenge' ];
if ( mode === 'subscribe' && token === process . env . WHATSAPP_VERIFY_TOKEN ) {
res . status ( 200 ). send ( challenge );
} else {
res . sendStatus ( 403 );
}
});
3. Handle Incoming Messages
app . post ( '/webhook/whatsapp' , async ( req , res ) => {
const { entry } = req . body ;
for ( const change of entry [ 0 ]. changes ) {
const message = change . value . messages ?.[ 0 ];
if ( message ?. type === 'text' ) {
await whatsappQueue . add ( 'process-message' , {
wamid: message . id ,
from: message . from ,
text: message . text . body
});
}
}
res . sendStatus ( 200 );
});
Memory Optimization
Current Configuration (Retriever.js:13-20)
async function getEmbeddingPipe () {
if ( ! embeddingPipe ) {
console . log ( "🔌 Loading Embedding Model (BYPASSED FOR RENDER FREE TIER OOM PROTECTION)..." );
// Bypass transformer load to save 300MB of RAM
embeddingPipe = () => { return { toList : () => new Array ( 1536 ). fill ( 0.0 ) } };
}
return embeddingPipe ;
}
This bypasses embedding generation to save ~300MB RAM on free-tier hosting. For production, enable real embeddings (see RAG System ).
Production Embedding Setup
For servers with >1GB RAM, use real embeddings:
import { pipeline } from '@xenova/transformers' ;
let embeddingPipe = null ;
async function getEmbeddingPipe () {
if ( ! embeddingPipe ) {
console . log ( "🔌 Loading Embedding Model..." );
embeddingPipe = await pipeline (
'feature-extraction' ,
'Xenova/all-MiniLM-L6-v2'
);
}
return embeddingPipe ;
}
Testing the Setup
1. Test Database Connection
import { PrismaClient } from '@prisma/client' ;
const prisma = new PrismaClient ();
async function testConnection () {
try {
const count = await prisma . product . count ();
console . log ( `✅ Database connected. Products: ${ count } ` );
} catch ( error ) {
console . error ( '❌ Database error:' , error );
}
}
testConnection ();
2. Test Redis Connection
import IORedis from 'ioredis' ;
const redis = new IORedis ( process . env . REDIS_URL );
redis . on ( 'connect' , () => console . log ( '✅ Redis connected' ));
redis . on ( 'error' , ( err ) => console . error ( '❌ Redis error:' , err ));
3. Test Claude API
import { ChatAnthropic } from '@langchain/anthropic' ;
import { HumanMessage } from '@langchain/core/messages' ;
const model = new ChatAnthropic ({
modelName: 'claude-3-haiku-20240307' ,
anthropicApiKey: process . env . ANTHROPIC_API_KEY ,
});
const response = await model . invoke ([
new HumanMessage ( 'Hola, ¿cómo estás?' )
]);
console . log ( '✅ Claude response:' , response . content );
4. Test WhatsApp Webhook
# Send test message
curl -X POST https://yourdomain.com/webhook/whatsapp \
-H "Content-Type: application/json" \
-d '{
"entry": [{
"changes": [{
"value": {
"messages": [{
"id": "wamid.test123",
"from": "573001234567",
"type": "text",
"text": { "body": "Hola" }
}]
}
}]
}]
}'
Deployment
Render.com
# render.yaml
services :
- type : web
name : kaiu-api
env : node
buildCommand : npm install && npx prisma generate
startCommand : npm start
envVars :
- key : DATABASE_URL
sync : false
- key : ANTHROPIC_API_KEY
sync : false
- key : NODE_TLS_REJECT_UNAUTHORIZED
value : "1"
- type : worker
name : kaiu-worker
env : node
buildCommand : npm install
startCommand : node backend/whatsapp/queue.js
Railway.app
// railway.json
{
"$schema" : "https://railway.app/railway.schema.json" ,
"build" : {
"builder" : "NIXPACKS"
},
"deploy" : {
"startCommand" : "npm start" ,
"restartPolicyType" : "ON_FAILURE" ,
"restartPolicyMaxRetries" : 10
}
}
Docker
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npx prisma generate
EXPOSE 3001
CMD [ "node" , "backend/server.js" ]
Health Checks
Add a health endpoint:
app . get ( '/health' , async ( req , res ) => {
const checks = {
database: false ,
redis: false ,
anthropic: false
};
try {
await prisma . $queryRaw `SELECT 1` ;
checks . database = true ;
} catch {}
try {
await redis . ping ();
checks . redis = true ;
} catch {}
const allHealthy = Object . values ( checks ). every ( v => v );
res . status ( allHealthy ? 200 : 503 ). json ( checks );
});
Troubleshooting
Error: ANTHROPIC_API_KEY is not set
Ensure .env file exists and contains: ANTHROPIC_API_KEY = "sk-ant-api03-..."
Restart the server after updating.
Error: P1001 - Can't reach database
Check DATABASE_URL format: postgresql://user:password@host:5432/database?schema =public
Verify PostgreSQL is running: psql -h localhost -U user -d database -c "SELECT 1"
Error: Redis connection refused
Ensure Redis is running: redis-cli ping # Should return PONG
Or start Docker container: docker run -d -p 6379:6379 redis:7-alpine
BullMQ jobs not processing
Check worker is running: node backend/whatsapp/queue.js
Verify Redis connection in logs. Ensure REDIS_URL or REDIS_HOST/REDIS_PORT are correct.
pgvector extension not found
Install pgvector on PostgreSQL: CREATE EXTENSION IF NOT EXISTS vector ;
If not available, use a managed service that supports it (Supabase, Neon).
Next Steps
Knowledge Base Management Populate the knowledge base with company policies
Prompt Engineering Optimize system prompts for better responses