Skip to content

Repository files navigation

Customer Service Chatbot

AI-powered customer service chatbot using DeepSeek (LLM) + SQLite (context database). Built with Node.js, Express, and vanilla frontend styled with Tailwind CSS.

Tech Stack

Layer Tech
Backend Node.js + Express
AI DeepSeek API (deepseek-chat)
Database SQLite (better-sqlite3)
Frontend Vanilla HTML + CSS + JS
Styling Tailwind CSS (CDN)
Markdown marked.js (CDN)

Project Structure

.
├── .env                  # Environment variables
├── .gitignore
├── package.json
├── server.js             # Express entry point, routes, static serve
├── cache.js              # In-memory TTL response cache
├── db.js                 # SQLite connection, LIKE search, full-table fetch
├── context.js            # Tokenizer, intent detection, context builder
├── ai.js                 # DeepSeek API client + caching layers
└── public/
    ├── index.html        # Chat UI
    ├── css/style.css     # Custom styles (scrollbar, markdown, typing anim)
    └── js/app.js         # Frontend chat client

Setup

npm install

Create a .env file:

DEEPSEEK_API_KEY=sk-your_key_here
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat

DB_PATH=./data.db
PORT=3000
CONTACT_EMAIL=cs@example.com

DS_TEMPERATURE=0.7
DS_TOP_P=0.9
DS_TOP_K=40
DS_MAX_TOKENS=2048
DS_PRESENCE_PENALTY=0
DS_FREQUENCY_PENALTY=0

Place your SQLite database file at the path specified in DB_PATH, then:

npm start

Open http://localhost:3000.

Database Schema

The chatbot expects a SQLite database with these tables:

abouts

Column Type Description
section_title TEXT Section heading (e.g. "Brand", "Vision")
content TEXT Body content

faqs

Column Type Description
question TEXT Frequently asked question
answer TEXT Corresponding answer

posts

Column Type Description
title TEXT Blog/article title
content TEXT Blog/article body

products

Column Type Description
name TEXT Product name
short_description TEXT Brief product summary
long_description TEXT Detailed product description
tags TEXT Comma-separated tags
link TEXT Product slug or URL
price TEXT Price as string

stores

Column Type Description
name TEXT Store name
address TEXT Store address

API

POST /api/chat

Send a user message and get an AI reply grounded in database context.

Request:

{
  "message": "Do you have aloe vera gel?"
}

Response:

{
  "reply": "Yes! We have Aloe Vera Gel — a soothing gel made from 92% aloe vera, priced at $12.99.",
  "hasData": true
}
Field Type Description
reply string AI-generated response
hasData boolean Whether relevant database context was found

Status codes:

  • 200 — Success
  • 400 — Missing message field
  • 500 — Internal server error (AI API failure, etc.)

Frontend

The public/ directory is served as static files. The chat UI sends POST /api/chat requests via fetch() and renders responses with markdown.

How Context Works

  1. Tokenize — User message is split into keywords (stop words removed)
  2. LIKE search — Each keyword is matched against all 5 tables via SQL LIKE
  3. Intent fallback — If a table has zero results but the message hints at it (e.g. "store", "toko", "price", "harga"), all rows from that table are fetched
  4. Context assembly — Results are formatted into a text block prefixed by section headers
  5. AI prompt — The context is injected into DeepSeek's system prompt; the AI must answer using only that data

Caching Strategy

Two layers:

Layer What it caches TTL Avoids
App cache (cache.js) Exact Q&A response (by MD5 hash of message + context) 1 hour Duplicate API calls entirely
DeepSeek auto cache Prompt prefix (system + context) on server side Automatic (≥1024 tokens) Resending cached prompt tokens

Console logs show cache efficiency: [App Cache] HIT, [DS Auto Cache] hit=X miss=Y.

Environment Variables

Variable Default Description
DEEPSEEK_API_KEY DeepSeek API key (required)
DEEPSEEK_BASE_URL https://api.deepseek.com API base URL
DEEPSEEK_MODEL deepseek-chat Model name
DB_PATH ./data.db Path to SQLite database
PORT 3000 HTTP server port
DS_TEMPERATURE 0.7 Response randomness
DS_TOP_P 0.9 Nucleus sampling
DS_TOP_K 40 Top-K sampling
DS_MAX_TOKENS 2048 Max response length
DS_PRESENCE_PENALTY 0 Penalize repeated topics
DS_FREQUENCY_PENALTY 0 Penalize repeated phrases

Language Support

English and Indonesian. Stop words and intent keywords are defined for both languages:

  • Intent tables map common query words to database tables:
    • store / tokostores
    • product / produkproducts
    • about / tentangabouts
    • faq / returfaqs
    • blog / artikelposts

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages