- correction of some bugs: - dynamic fields for adding documents / urls to dossier catalog - tabs in latest bootstrap version no longer functional - partner association of license tier not working when no partner selected - data-type dynamic field needs conversion to isoformat - Add public tables to env.py of tenant schema
516 lines
16 KiB
Markdown
516 lines
16 KiB
Markdown
# Evie Chat Client - Developer Documentation
|
|
|
|
## Overview
|
|
|
|
The Evie Chat Client is a modern, customizable chat interface for interacting with eveai specialists. It supports both anonymous and authenticated modes, with initial focus on anonymous mode. The client provides real-time interaction with AI specialists, customizable tenant branding, European-compliant analytics tracking, and secure QR code access.
|
|
|
|
## Key Features
|
|
|
|
- **Anonymous Mode**: Public access with tenant UUID and API key authentication
|
|
- **QR Code Access**: Secure pre-authenticated landing pages for QR code integration
|
|
- **Real-time Communication**: Server-Sent Events (SSE) for live updates and intermediate states
|
|
- **Tenant Customization**: Simple CSS variable-based theming with visual editor
|
|
- **Multiple Choice Options**: Dynamic button/dropdown responses from specialists
|
|
- **Chat History**: Persistent ChatSession and Interaction storage
|
|
- **File Upload Support**: Planned for future implementation
|
|
- **European Analytics**: Umami integration for GDPR-compliant tracking
|
|
|
|
## Architecture
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
evie-project/
|
|
├── common/ # Shared code across components
|
|
│ ├── services/ # Reusable business logic
|
|
│ │ ├── chat_service.py # Chat session management
|
|
│ │ ├── specialist_service.py # Specialist interaction wrapper
|
|
│ │ ├── tenant_service.py # Tenant config & theming
|
|
│ │ └── qr_service.py # QR code session management
|
|
│ └── utils/ # Utility functions
|
|
│ ├── auth.py # API key validation
|
|
│ ├── tracking.py # Umami analytics integration
|
|
│ └── qr_utils.py # QR code generation utilities
|
|
├── eveai_chat_client/ # Chat client component
|
|
│ ├── app.py # Flask app entry point
|
|
│ ├── routes/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── chat_routes.py # Main chat interface routes
|
|
│ │ ├── api_routes.py # SSE/API endpoints
|
|
│ │ └── qr_routes.py # QR code landing pages
|
|
│ └── templates/
|
|
│ ├── base.html # Base template
|
|
│ ├── chat.html # Main chat interface
|
|
│ ├── qr_expired.html # QR code error page
|
|
│ └── components/
|
|
│ ├── message.html # Individual message component
|
|
│ ├── options.html # Multiple choice options
|
|
│ └── thinking.html # Intermediate states display
|
|
└── eveai_app/ # Admin interface (existing)
|
|
└── qr_management/ # QR code creation interface
|
|
├── create_qr.py
|
|
└── qr_templates.html
|
|
```
|
|
|
|
### Integration Approach
|
|
|
|
- **Services Layer**: Direct integration with common/services for better performance
|
|
- **Database**: Utilizes existing ChatSession and Interaction models
|
|
- **Caching**: Leverages existing Redis setup
|
|
- **Static Files**: Uses existing nginx/static structure
|
|
|
|
## QR Code Access Flow
|
|
|
|
### QR Code System Architecture
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Admin as Admin (eveai_app)
|
|
participant QRService as QR Service (common)
|
|
participant PublicDB as Public Schema
|
|
participant TenantDB as Tenant Schema
|
|
participant User as End User
|
|
participant ChatClient as Chat Client
|
|
participant ChatSession as Chat Session
|
|
|
|
%% QR Code Creation Flow
|
|
Admin->>QRService: Create QR code with specialist config
|
|
QRService->>PublicDB: Store qr_lookup (qr_id → tenant_code)
|
|
QRService->>TenantDB: Store qr_sessions (full config + args)
|
|
QRService->>Admin: Return QR code image with /qr/{qr_id}
|
|
|
|
%% QR Code Usage Flow
|
|
User->>ChatClient: Scan QR → GET /qr/{qr_id}
|
|
ChatClient->>PublicDB: Lookup tenant_code by qr_id
|
|
ChatClient->>TenantDB: Get full QR session data
|
|
ChatClient->>ChatSession: Create ChatSession with pre-filled args
|
|
ChatClient->>User: Set temp auth + redirect to chat interface
|
|
User->>ChatClient: Access chat with pre-authenticated session
|
|
```
|
|
|
|
### QR Code Data Flow
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[Admin Creates QR Code] --> B[Generate UUID for QR Session]
|
|
B --> C[Store Lookup in Public Schema]
|
|
C --> D[Store Full Data in Tenant Schema]
|
|
D --> E[Generate QR Code Image]
|
|
|
|
F[User Scans QR Code] --> G[Extract QR Session ID from URL]
|
|
G --> H[Lookup Tenant Code in Public Schema]
|
|
H --> I[Retrieve Full QR Data from Tenant Schema]
|
|
I --> J{QR Valid & Not Expired?}
|
|
J -->|No| K[Show Error Page]
|
|
J -->|Yes| L[Create ChatSession with Pre-filled Args]
|
|
L --> M[Set Temporary Browser Authentication]
|
|
M --> N[Redirect to Chat Interface]
|
|
N --> O[Start Chat with Specialist]
|
|
```
|
|
|
|
## URL Structure & Parameters
|
|
|
|
### Main Chat Interface
|
|
```
|
|
GET /chat/{tenant_code}/{specialist_id}
|
|
```
|
|
|
|
**Query Parameters:**
|
|
- `api_key` (required for direct access): Tenant API key for authentication
|
|
- `session` (optional): Existing chat session ID
|
|
- `utm_source`, `utm_campaign`, `utm_medium` (optional): Analytics tracking
|
|
|
|
**Examples:**
|
|
```
|
|
# Direct access
|
|
/chat/550e8400-e29b-41d4-a716-446655440000/document-analyzer?api_key=xxx&utm_source=email
|
|
|
|
# QR code access (after redirect)
|
|
/chat/550e8400-e29b-41d4-a716-446655440000/document-analyzer?session=abc123-def456
|
|
```
|
|
|
|
### QR Code Landing Pages
|
|
```
|
|
GET /qr/{qr_session_id} # QR code entry point (redirects, no HTML page)
|
|
```
|
|
|
|
### API Endpoints
|
|
```
|
|
POST /api/chat/{tenant_code}/interact # Send message to specialist
|
|
GET /api/chat/{tenant_code}/status/{session_id} # SSE endpoint for updates
|
|
```
|
|
|
|
## Authentication & Security
|
|
|
|
### Anonymous Mode Access Methods
|
|
|
|
1. **Direct Access**: URL with API key parameter
|
|
2. **QR Code Access**: Pre-authenticated via secure landing page
|
|
|
|
### QR Code Security Model
|
|
- **QR Code Contains**: Only a UUID session identifier
|
|
- **Sensitive Data**: Stored securely in tenant database schema
|
|
- **Usage Control**: Configurable expiration and usage limits
|
|
- **Audit Trail**: Track QR code creation and usage
|
|
|
|
### Security Considerations
|
|
- Use tenant UUIDs to prevent enumeration attacks
|
|
- Validate API keys against tenant database
|
|
- Implement CORS policies for cross-origin requests
|
|
- Sanitize all user messages and file uploads
|
|
- QR sessions have configurable expiration and usage limits
|
|
|
|
## QR Code Management
|
|
|
|
### Database Schema
|
|
|
|
#### Public Schema (Routing Only)
|
|
```sql
|
|
CREATE TABLE qr_lookup (
|
|
qr_session_id UUID PRIMARY KEY,
|
|
tenant_code UUID NOT NULL,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
INDEX idx_tenant_code (tenant_code)
|
|
);
|
|
```
|
|
|
|
#### Tenant Schema (Full QR Data)
|
|
```sql
|
|
CREATE TABLE qr_sessions (
|
|
id UUID PRIMARY KEY,
|
|
specialist_id UUID NOT NULL,
|
|
api_key VARCHAR(255) NOT NULL,
|
|
specialist_args JSONB,
|
|
metadata JSONB,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
expires_at TIMESTAMP,
|
|
usage_count INTEGER DEFAULT 0,
|
|
usage_limit INTEGER,
|
|
created_by_user_id UUID
|
|
);
|
|
```
|
|
|
|
### QR Code Creation (eveai_app)
|
|
```python
|
|
# In eveai_app admin interface
|
|
from common.services.qr_service import QRService
|
|
|
|
def create_specialist_qr_code():
|
|
qr_data = {
|
|
'tenant_code': current_tenant.code,
|
|
'specialist_id': selected_specialist.id,
|
|
'api_key': current_tenant.api_key,
|
|
'specialist_args': {
|
|
'department': 'sales',
|
|
'language': 'en',
|
|
'context': 'product_inquiry'
|
|
},
|
|
'metadata': {
|
|
'name': 'Sales Support QR - Product Brochure',
|
|
'usage_limit': 500,
|
|
'expires_days': 90
|
|
}
|
|
}
|
|
|
|
qr_service = QRService()
|
|
qr_session_id, qr_image = qr_service.create_qr_session(qr_data)
|
|
return qr_image
|
|
```
|
|
|
|
### QR Code Processing (eveai_chat_client)
|
|
```python
|
|
# In eveai_chat_client routes
|
|
from common.services.qr_service import QRService
|
|
from common.services.chat_service import ChatService
|
|
|
|
@app.route('/qr/<qr_session_id>')
|
|
def handle_qr_code(qr_session_id):
|
|
qr_service = QRService()
|
|
qr_data = qr_service.get_and_validate_qr_session(qr_session_id)
|
|
|
|
if not qr_data:
|
|
return render_template('qr_expired.html'), 410
|
|
|
|
# Create ChatSession with pre-filled arguments
|
|
chat_service = ChatService()
|
|
chat_session = chat_service.create_session(
|
|
tenant_code=qr_data['tenant_code'],
|
|
specialist_id=qr_data['specialist_id'],
|
|
initial_args=qr_data['specialist_args'],
|
|
source='qr_code'
|
|
)
|
|
|
|
# Set temporary authentication
|
|
flask_session['qr_auth'] = {
|
|
'tenant_code': qr_data['tenant_code'],
|
|
'api_key': qr_data['api_key'],
|
|
'chat_session_id': chat_session.id,
|
|
'expires_at': datetime.utcnow() + timedelta(hours=24)
|
|
}
|
|
|
|
# Redirect to chat interface
|
|
return redirect(f"/chat/{qr_data['tenant_code']}/{qr_data['specialist_id']}?session={chat_session.id}")
|
|
```
|
|
|
|
## Real-time Communication
|
|
|
|
### Server-Sent Events (SSE)
|
|
- **Connection**: Long-lived SSE connection per chat session
|
|
- **Message Types**:
|
|
- `message`: Complete specialist response
|
|
- `thinking`: Intermediate processing states
|
|
- `options`: Multiple choice response options
|
|
- `error`: Error messages
|
|
- `complete`: Interaction completion
|
|
|
|
### SSE Message Format
|
|
```json
|
|
{
|
|
"type": "thinking",
|
|
"data": {
|
|
"message": "Analyzing your request...",
|
|
"step": 1,
|
|
"total_steps": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
## Tenant Customization
|
|
|
|
### Theme Configuration
|
|
Stored in tenant table as JSONB column:
|
|
```sql
|
|
ALTER TABLE tenants ADD COLUMN theme_config JSONB;
|
|
```
|
|
|
|
### CSS Variables Approach
|
|
Inline CSS variables in chat template:
|
|
```css
|
|
:root {
|
|
/* Brand Colors */
|
|
--primary-color: {{ tenant.theme_config.primary_color or '#007bff' }};
|
|
--secondary-color: {{ tenant.theme_config.secondary_color or '#6c757d' }};
|
|
--accent-color: {{ tenant.theme_config.accent_color or '#28a745' }};
|
|
|
|
/* Chat Interface */
|
|
--user-message-bg: {{ tenant.theme_config.user_message_bg or 'var(--primary-color)' }};
|
|
--bot-message-bg: {{ tenant.theme_config.bot_message_bg or '#f8f9fa' }};
|
|
--chat-bg: {{ tenant.theme_config.chat_bg or '#ffffff' }};
|
|
|
|
/* Typography */
|
|
--font-family: {{ tenant.theme_config.font_family or 'system-ui, -apple-system, sans-serif' }};
|
|
--font-size-base: {{ tenant.theme_config.font_size or '16px' }};
|
|
|
|
/* Branding */
|
|
--logo-url: url('/api/tenant/{{ tenant.code }}/logo');
|
|
--header-bg: {{ tenant.theme_config.header_bg or 'var(--primary-color)' }};
|
|
}
|
|
```
|
|
|
|
### Theme Editor (eveai_app)
|
|
Simple form interface with:
|
|
- Color pickers for brand colors
|
|
- Font selection dropdown
|
|
- Logo upload functionality
|
|
- Live preview of chat interface
|
|
- Reset to defaults option
|
|
|
|
## Multiple Choice Options
|
|
|
|
### Dynamic Rendering Logic
|
|
```python
|
|
def render_options(options_list):
|
|
if len(options_list) <= 3:
|
|
return render_template('components/options.html',
|
|
display_type='buttons',
|
|
options=options_list)
|
|
else:
|
|
return render_template('components/options.html',
|
|
display_type='dropdown',
|
|
options=options_list)
|
|
```
|
|
|
|
### Option Data Structure
|
|
```json
|
|
{
|
|
"type": "options",
|
|
"data": {
|
|
"question": "How would you like to proceed?",
|
|
"options": [
|
|
{"id": "option1", "text": "Continue analysis", "value": "continue"},
|
|
{"id": "option2", "text": "Generate report", "value": "report"},
|
|
{"id": "option3", "text": "Start over", "value": "restart"}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Analytics Integration
|
|
|
|
### Umami Setup
|
|
- **European Hosting**: Self-hosted Umami instance
|
|
- **Privacy Compliant**: No cookies, GDPR compliant by design
|
|
- **Tracking Events**:
|
|
- Chat session start (including QR code source)
|
|
- Message sent
|
|
- Option selected
|
|
- Session duration
|
|
- Specialist interaction completion
|
|
- QR code usage
|
|
|
|
### Tracking Implementation
|
|
```javascript
|
|
// Track chat events
|
|
function trackEvent(eventName, eventData) {
|
|
if (window.umami) {
|
|
umami.track(eventName, eventData);
|
|
}
|
|
}
|
|
|
|
// Track QR code usage
|
|
function trackQRUsage(qrSessionId, tenantCode) {
|
|
trackEvent('qr_code_used', {
|
|
qr_session_id: qrSessionId,
|
|
tenant_code: tenantCode
|
|
});
|
|
}
|
|
```
|
|
|
|
## File Upload Support (Future)
|
|
|
|
### Planned Implementation
|
|
- **Multipart Upload**: Standard HTML5 file upload
|
|
- **File Types**: Documents, images, spreadsheets
|
|
- **Storage**: Tenant-specific S3 buckets
|
|
- **Processing**: Integration with existing document processing pipeline
|
|
- **UI**: Drag-and-drop interface with progress indicators
|
|
|
|
### Security Considerations
|
|
- File type validation
|
|
- Size limits per tenant
|
|
- Virus scanning integration
|
|
- Temporary file cleanup
|
|
|
|
## Development Guidelines
|
|
|
|
### Code Organization
|
|
- **Services**: Place reusable business logic in `common/services/`
|
|
- **Utils**: Place utility functions in `common/utils/`
|
|
- **Multi-tenant**: Maintain data isolation using existing patterns
|
|
- **Error Handling**: Implement proper error handling and logging
|
|
|
|
### Service Layer Examples
|
|
```python
|
|
# common/services/qr_service.py
|
|
class QRService:
|
|
def create_qr_session(self, qr_data):
|
|
# Create QR session with hybrid storage approach
|
|
pass
|
|
|
|
def get_and_validate_qr_session(self, qr_session_id):
|
|
# Validate and retrieve QR session data
|
|
pass
|
|
|
|
# common/services/chat_service.py
|
|
class ChatService:
|
|
def create_session(self, tenant_code, specialist_id, initial_args=None, source='direct'):
|
|
# Create chat session with optional pre-filled arguments
|
|
pass
|
|
```
|
|
|
|
### Testing Strategy
|
|
- Unit tests for services and utilities in `common/`
|
|
- Integration tests for chat flow including QR code access
|
|
- UI tests for theme customization
|
|
- Load testing for SSE connections
|
|
- Cross-browser compatibility testing
|
|
|
|
### Performance Considerations
|
|
- Cache tenant configurations in Redis
|
|
- Cache QR session lookups in Redis
|
|
- Optimize SSE connection management
|
|
- Implement connection pooling for database
|
|
- Use CDN for static assets
|
|
- Monitor real-time connection limits
|
|
|
|
## Deployment
|
|
|
|
### Container Configuration
|
|
- New `eveai_chat_client` container
|
|
- Integration with existing docker setup
|
|
- Environment configuration for tenant isolation
|
|
- Load balancer configuration for SSE connections
|
|
|
|
### Dependencies
|
|
- Flask and Flask-restx (existing)
|
|
- Celery integration (existing)
|
|
- PostgreSQL and Redis (existing)
|
|
- Umami analytics client library
|
|
- QR code generation library (qrcode)
|
|
|
|
## Future Enhancements
|
|
|
|
### Authenticated Mode
|
|
- User login integration
|
|
- Session persistence across devices
|
|
- Advanced specialist access controls
|
|
- User-specific chat history
|
|
|
|
### Advanced Features
|
|
- Voice message support
|
|
- Screen sharing capabilities
|
|
- Collaborative chat sessions
|
|
- Advanced analytics dashboard
|
|
- Mobile app integration
|
|
|
|
## Configuration Examples
|
|
|
|
### Environment Variables
|
|
```bash
|
|
CHAT_CLIENT_PORT=5000
|
|
TENANT_API_VALIDATION_CACHE_TTL=3600
|
|
SSE_CONNECTION_TIMEOUT=300
|
|
QR_SESSION_DEFAULT_EXPIRY_DAYS=30
|
|
QR_SESSION_MAX_USAGE_LIMIT=1000
|
|
UMAMI_WEBSITE_ID=your-website-id
|
|
UMAMI_SCRIPT_URL=https://your-umami.domain/script.js
|
|
```
|
|
|
|
### Sample Theme Configuration
|
|
```json
|
|
{
|
|
"primary_color": "#2563eb",
|
|
"secondary_color": "#64748b",
|
|
"accent_color": "#059669",
|
|
"user_message_bg": "#2563eb",
|
|
"bot_message_bg": "#f1f5f9",
|
|
"chat_bg": "#ffffff",
|
|
"font_family": "Inter, system-ui, sans-serif",
|
|
"font_size": "16px",
|
|
"header_bg": "#1e40af"
|
|
}
|
|
```
|
|
|
|
### Sample QR Session Data
|
|
```json
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"tenant_code": "123e4567-e89b-12d3-a456-426614174000",
|
|
"specialist_id": "789e0123-e45f-67g8-h901-234567890123",
|
|
"api_key": "tenant_api_key_here",
|
|
"specialist_args": {
|
|
"department": "technical_support",
|
|
"product_category": "software",
|
|
"priority": "high",
|
|
"language": "en"
|
|
},
|
|
"metadata": {
|
|
"name": "Technical Support QR - Software Issues",
|
|
"created_by": "admin_user_id",
|
|
"usage_limit": 100,
|
|
"expires_at": "2025-09-01T00:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
This documentation provides a comprehensive foundation for developing the Evie Chat Client with secure QR code integration while maintaining consistency with the existing eveai multi-tenant architecture. |