🤖 AI Chatbot Architecture

Complete Technical Flow Documentation

Project: Bailey Engineering CMS Date: October 17, 2025 Version: 1.0

System Overview

High-Level Architecture

┌─────────────────────────────────────────────────────────────────┐
│                         USER INTERFACE                          │
│                    (Browser - JavaScript)                       │
└────────────┬────────────────────────────────────────────────────┘
             │
             │ 1. User types: "What projects do we have?"
             │ 2. Click Send Button
             │
             ▼
┌─────────────────────────────────────────────────────────────────┐
│                      FRONTEND LAYER                             │
│                   chat-widget.js                                │
│  • Capture user input                                           │
│  • Validate message                                             │
│  • Send POST request to API                                     │
│  • Display response                                             │
└────────────┬────────────────────────────────────────────────────┘
             │
             │ HTTP POST /api/chat.php
             │ JSON: { "message": "...", "conversation_id": "..." }
             │
             ▼
┌─────────────────────────────────────────────────────────────────┐
│                      API ENDPOINT                               │
│                     api/chat.php                                │
│  • Receive request                                              │
│  • Security checks (rate limiting, validation)                  │
│  • Route to processing                                          │
└────────────┬────────────────────────────────────────────────────┘
             │
             ├──────────────────────────────────────┐
             │                                      │
             ▼                                      ▼
┌──────────────────────────┐         ┌─────────────────────────┐
│   DATABASE QUERY         │         │   AI INTEGRATION        │
│   database-query.php     │         │   ai-integration.php    │
│                          │         │                         │
│ • Extract keywords       │         │ • Build prompt          │
│ • Determine search scope │         │ • Call Claude API       │
│ • Query databases        │         │ • Parse response        │
│ • Format results         │         │                         │
└──────────┬───────────────┘         └─────────┬───────────────┘
           │                                   │
           │ Database Context                  │ AI Response
           │                                   │
           ▼                                   ▼
┌─────────────────────────────────────────────────────────────────┐
│                    DATABASE LAYER                               │
│                                                                 │
│  ┌─────────────────────┐       ┌──────────────────────┐       │
│  │  blackfla_Cms       │       │ blackfla_Project     │       │
│  │                     │       │ Tracker              │       │
│  │ • projects          │       │                      │       │
│  │ • contracts         │       │ • projects           │       │
│  │ • clients           │       │ • submittal_events   │       │
│  │ • agencies          │       │ • agencies           │       │
│  └─────────────────────┘       └──────────────────────┘       │
└─────────────────────────────────────────────────────────────────┘
           │                                   │
           └───────────────┬───────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                    RESPONSE ASSEMBLY                            │
│                                                                 │
│  • Combine database results + AI response                      │
│  • Format as JSON                                              │
│  • Return to frontend                                          │
└────────────┬────────────────────────────────────────────────────┘
             │
             │ JSON Response
             │ { "success": true, "response": "...", ... }
             │
             ▼
┌─────────────────────────────────────────────────────────────────┐
│                    FRONTEND DISPLAY                             │
│  • Parse JSON response                                          │
│  • Display AI message in chat                                   │
│  • Scroll to bottom                                            │
└─────────────────────────────────────────────────────────────────┘

Complete Request Flow

Step-by-Step Process

USER ACTION → VALIDATION → SECURITY → DATABASE → AI → RESPONSE

Detailed 20-Step Flow

Each user message goes through 20 distinct processing steps:

  1. User Input - User types message and clicks send
  2. Frontend Validation - Check message is not empty and within limits
  3. Prepare API Request - Display message, show loading indicator
  4. Send HTTP Request - POST to /api/chat.php
  5. API Receives Request - Load dependencies
  6. Security Validation - Check method, JSON, rate limits
  7. Input Sanitization - Remove HTML, special chars
  8. Keyword Extraction - Parse message for search terms
  9. Determine Search Scope - Decide which databases to query
  10. Database Connection - Connect to CMS & Tracker DBs
  11. Query Databases - Execute SQL queries
  12. Check Tracker Data - Get milestone/submittal info if needed
  13. Format Results for AI - Convert to readable string
  14. Build AI Prompt - Create structured prompt
  15. Call Claude AI API - Send to Claude
  16. Error Handling - Check for API errors
  17. Prepare Response - Format JSON response
  18. Send to Frontend - Transmit over network
  19. Frontend Receives Response - Parse JSON
  20. Display Response - Show in chat UI
⏱ Total Time: Typically 2-5 seconds from user click to AI response displayed

Frontend Layer

File: prototype/js/chat-widget.js

Key Functions

1. initChatWidget()

Purpose: Initialize the chat widget on page load
Actions:
  • Check if enabled (localStorage)
  • Create HTML elements
  • Attach event listeners
  • Load conversation ID
  • Display welcome message

2. sendMessage()

Purpose: Send user message to API
Flow:
  1. Validate message not empty
  2. Validate message length ≤ 500
  3. Display user message
  4. Show loading indicator
  5. Make fetch() POST request
  6. Handle response or error
  7. Display AI response
  8. Re-enable input

3. displayMessage(content, type)

Purpose: Add message to chat UI
Parameters:
  • content: Message text
  • type: 'user' | 'ai' | 'error' | 'welcome'
Actions:
  • Create message div
  • Apply appropriate styling
  • Format content (line breaks)
  • Append to messages container
  • Scroll to bottom

Backend Processing

File: api/chat.php

Main Flow

1. Load Dependencies
   ↓
2. Receive POST Request
   ↓
3. Validate Request Method → [Not POST] Return 405
   ↓
4. Parse JSON Body → [Invalid] Return 400
   ↓
5. Validate Message Field → [Missing] Return 400
   ↓
6. Sanitize Message
   ↓
7. Validate Message Length → [Invalid] Return 400
   ↓
8. Check Rate Limit → [Exceeded] Return 429
   ↓
9. Get/Generate Conversation ID
   ↓
10. Try-Catch Block:
    ├─ Search Databases
    ├─ Format Results
    ├─ Call AI
    ├─ Return Success Response
    └─ [Error] Log & Return 500

Security Layers

Layer 1: CORS (config/cors.php)

  • Check origin
  • Set Access-Control headers
  • Handle OPTIONS preflight
  • Set Content-Type

Layer 2: Rate Limiting (config/security.php)

Class: RateLimiter
Storage: .rate_limits.json

Logic:
• Track requests per IP address
• Window: 60 seconds
• Limit: 10 requests
• Action: Block if exceeded
• Cleanup: Remove old entries

Layer 3: Input Validation

  • Check method
  • Validate JSON
  • Check required fields
  • Validate data types
  • Sanitize strings

Database Query Logic

File: api/helpers/database-query.php

Decision Tree

User Message
     │
     ▼
Extract Keywords
     │
     ├─ Remove stop words
     ├─ Filter short words
     └─ Return array of keywords
     │
     ▼
Analyze Message Patterns
     │
     ├─ Check for "list all" patterns
     │   • Regex: /(all|list|show|how many|count)/i
     │   • If matches + contains "project" → List ALL projects
     │
     ├─ Check keyword presence
     │   • containsKeywords(['project', 'projects']) → Search Projects
     │   • containsKeywords(['contract', 'contracts']) → Search Contracts
     │   • containsKeywords(['client', 'clients']) → Search Clients
     │   • containsKeywords(['submittal', ...]) → Search Submittals
     │   • containsKeywords(['approval', ...]) → Search Approvals
     │   • containsKeywords(['status', 'phase', ...]) → Get Milestones
     │
     ▼
Execute Appropriate Queries
     │
     ├─ IF (listAllProjects):
     │   └─ getAllCmsProjects($db, 10)
     │       → SELECT * FROM projects LIMIT 10
     │
     ├─ IF (searchProjects && !listAllProjects):
     │   └─ searchCmsProjects($db, $keywords, 5)
     │       → SELECT * FROM projects WHERE ... LIKE %keyword%
     │
     ├─ IF (searchContracts):
     │   └─ searchCmsContracts($db, $keywords, 5)
     │
     ├─ IF (searchClients):
     │   └─ searchCmsClients($db, $keywords, 5)
     │
     ├─ IF (projects found && searchMilestones):
     │   └─ getTrackerProjectMilestones($trackerDb, $projectNumber)
     │
     └─ IF (projects found && searchSubmittals):
         └─ searchTrackerSubmittalEvents($trackerDb, $projectNumber, 5)

Query Functions

getAllCmsProjects($db, $limit)

Purpose: Get all projects (for "list all" queries)

SELECT 
  p.project_id, p.project_number, p.project_name,
  p.project_status, p.total_lots_units,
  c.client_name, a.agency_name
FROM projects p
LEFT JOIN clients c ON p.client_id = c.client_id
LEFT JOIN agencies a ON p.lead_agency_id = a.agency_id
ORDER BY p.updated_at DESC
LIMIT :limit

searchCmsProjects($db, $keywords, $limit)

Purpose: Search projects by keywords

WHERE p.project_number LIKE :keyword
   OR p.project_name LIKE :keyword
   OR c.client_name LIKE :keyword
LIMIT :limit

AI Integration

File: api/helpers/ai-integration.php

Prompt Engineering

Component Breakdown

1. System Context (Role Definition)

  • Identity: "You are a helpful assistant for Bailey Engineering"
  • Purpose: "Help users find information about projects, contracts..."
  • Behavior: "Be concise, friendly, and professional"
  • Constraints: "Answer based on database information provided"
  • Formatting: "Use bullet points, format dates nicely"
  • Honesty: "If you don't have information, say so clearly"

2. Database Context (Facts)

  • Structured data from database queries
  • Formatted as readable text
  • Includes all relevant details
  • Clearly labeled by section (PROJECTS, CONTRACTS, etc.)

3. User Question (Query)

  • Exact user message
  • Labeled as "USER QUESTION:"

4. Instructions (Guidelines)

  • "Provide a helpful answer based on database information"
  • "If no relevant information found, say so politely"

API Call Process

Request Structure

{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "[Complete Prompt]"
    }
  ]
}

Error Scenarios

Status Code Meaning User Message
200 Success Display AI response
401 Auth Failed "Authentication issue"
429 Rate Limited "Too many requests"
500 Server Error "Service unavailable"
Timeout No Response "Request timed out"
Network Error Connection Failed "Unable to connect"

Response Processing

How AI Evaluates and Responds

1. Claude's Internal Process

Input: Complete prompt with context
  ↓
Parse Components:
  • Understand role (assistant for engineering firm)
  • Read database facts
  • Analyze user question
  ↓
Reasoning:
  • User asks: "How many projects do we have?"
  • Database shows: 10 project records
  • Task: Count and summarize
  ↓
Generate Response:
  • Start with direct answer: "We have 10 projects"
  • Provide details: List project names
  • Add context: Include client info, status
  • Format nicely: Use bullets/numbers
  ↓
Output: Formatted text response

2. Response Quality Factors

Good Prompt = Good Response
  • ✓ Clear system context
  • ✓ Structured database facts
  • ✓ Specific user question
  • ✓ Clear instructions
  • = High-quality, relevant response

Error Handling

Error Messages

User-Facing (Friendly)

  • "Please enter a message"
  • "Message is too long (max 500 characters)"
  • "Unable to connect. Please try again"
  • "Too many requests. Please wait 30 seconds"
  • "An error occurred. Please try again"

Developer-Facing (Logged)

  • "Chat API error: [exception message]"
  • "Database connection failed: [details]"
  • "Claude API error: HTTP 429 - [response]"
  • "Rate limit check for IP: [ip_address]"

Performance Metrics

Timing Breakdown

Total Request Time: ~2-5 seconds

Component Time
Frontend Processing ~50ms
Network to Server ~20-50ms
Security Validation ~10ms
Database Queries ~50-100ms
Format for AI ~5ms
Claude API Call ~1-3s ← Largest component
Response Processing ~10ms
Network to Client ~20-50ms
Frontend Display ~20ms

Optimization Points

  1. Database Queries: < 100ms (indexed searches)
  2. AI API: 1-3 seconds (external service)
  3. Rate Limiting: File-based (fast access)
  4. Caching: Conversation ID in sessionStorage

Summary

Key Components

  1. Frontend: chat-widget.js - User interface
  2. API Endpoint: chat.php - Request router
  3. Security: security.php - Rate limiting
  4. Database: database-query.php - Search logic
  5. AI: ai-integration.php - Claude API
  6. Databases: CMS + ProjectTracker

Data Flow

User Input → Validation → Security → Database Search → AI Processing → Response

Decision Points

  1. Which database to query? → Keyword analysis
  2. List all or search? → Pattern detection
  3. Include milestones? → Keyword presence
  4. Include submittals? → Keyword presence

Success Factors

  • ✅ Clear user questions
  • ✅ Relevant database results
  • ✅ Well-structured prompts
  • ✅ Fast database queries
  • ✅ Proper error handling
📝 Document Version: 1.0
📅 Last Updated: October 17, 2025
✅ Status: Complete Technical Documentation