Deeksha commited on
Commit
374233e
·
0 Parent(s):

Initial deployment to Hugging Face Spaces

Browse files
Files changed (6) hide show
  1. Dockerfile +17 -0
  2. README.md +25 -0
  3. app.py +92 -0
  4. requirements.txt +8 -0
  5. static/css/style.css +244 -0
  6. templates/index.html +196 -0
Dockerfile ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update && apt-get install -y \
6
+ build-essential \
7
+ && rm -rf /var/lib/apt-lists/*
8
+
9
+ COPY requirements.txt .
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ COPY . .
13
+
14
+ # Expose port 7860 for Hugging Face Spaces
15
+ EXPOSE 7860
16
+
17
+ CMD ["python", "app.py"]
README.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Chatbot Performance Analyzer
3
+ emoji: 🤖
4
+ colorFrom: indigo
5
+ colorTo: pink
6
+ sdk: docker
7
+ pinned: false
8
+ license: apache-2.0
9
+ ---
10
+
11
+ # Chatbot Performance Analyzer
12
+
13
+ An advanced AI system that evaluates chatbot responses using Bidirectional LSTM with Attention mechanism. The model analyzes responses based on contextual facts to determine quality and accuracy.
14
+
15
+ ## Features
16
+ - Context-aware performance evaluation
17
+ - Attention-based LSTM architecture
18
+ - Real-time analytics dashboard
19
+ - Glassmorphic modern UI
20
+
21
+ ## Usage
22
+ 1. Enter related facts/context
23
+ 2. Provide the user question
24
+ 3. Input the chatbot's response
25
+ 4. Get instant expert analysis
app.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import numpy as np
4
+ import tensorflow as tf
5
+ from tensorflow.keras.preprocessing.sequence import pad_sequences
6
+ from flask import Flask, render_template, request, jsonify
7
+ from flask_cors import CORS
8
+ from huggingface_hub import hf_hub_download
9
+
10
+ app = Flask(__name__)
11
+ CORS(app)
12
+
13
+ # Configuration
14
+ MAX_LEN = 300
15
+ REPO_ID = "d-e-e-k-11/chatbot-performance-analyzer"
16
+
17
+ # Global variables
18
+ model = None
19
+ tokenizer = None
20
+
21
+ # Custom Attention Layer
22
+ class Attention(tf.keras.layers.Layer):
23
+ def __init__(self, **kwargs):
24
+ super(Attention, self).__init__(**kwargs)
25
+ def build(self, input_shape):
26
+ self.W = self.add_weight(name='attention_weight', shape=(input_shape[-1], 1), initializer='random_normal', trainable=True)
27
+ self.b = self.add_weight(name='attention_bias', shape=(input_shape[1], 1), initializer='zeros', trainable=True)
28
+ super(Attention, self).build(input_shape)
29
+ def call(self, x):
30
+ e = tf.keras.backend.tanh(tf.keras.backend.dot(x, self.W) + self.b)
31
+ a = tf.keras.backend.softmax(e, axis=1)
32
+ output = x * a
33
+ return tf.keras.backend.sum(output, axis=1)
34
+
35
+ def load_resources():
36
+ global model, tokenizer
37
+ try:
38
+ # Download from Hugging Face Hub
39
+ model_path = hf_hub_download(repo_id=REPO_ID, filename="chatbot_performance_advanced.h5", repo_type="space")
40
+ tokenizer_path = hf_hub_download(repo_id=REPO_ID, filename="tokenizer_advanced.pickle", repo_type="space")
41
+
42
+ model = tf.keras.models.load_model(model_path, custom_objects={'Attention': Attention})
43
+ with open(tokenizer_path, 'rb') as handle:
44
+ tokenizer = pickle.load(handle)
45
+ print("Advanced Model and Tokenizer loaded successfully from Hub.")
46
+ return True
47
+ except Exception as e:
48
+ print(f"Error loading resources: {e}")
49
+ return False
50
+
51
+ @app.route('/')
52
+ def index():
53
+ return render_template('index.html')
54
+
55
+ @app.route('/predict', methods=['POST'])
56
+ def predict():
57
+ global model, tokenizer
58
+ if model is None or tokenizer is None:
59
+ if not load_resources():
60
+ return jsonify({
61
+ 'error': 'Model is still loading. Please wait a moment.',
62
+ 'status': 'loading'
63
+ }), 503
64
+
65
+ data = request.json
66
+ if data.get('ping'):
67
+ return jsonify({'status': 'ready'})
68
+
69
+ facts = data.get('facts', 'No context provided.')
70
+ question = data.get('question', '')
71
+ response = data.get('response', '')
72
+
73
+ try:
74
+ # Preprocess text with facts context
75
+ text = f"[FACTS] {facts} [QUERY] {question} [RES] {response}".lower()
76
+ seq = tokenizer.texts_to_sequences([text])
77
+ pad = pad_sequences(seq, maxlen=MAX_LEN)
78
+
79
+ # Prediction
80
+ prediction = model.predict(pad)[0][0]
81
+ is_best = bool(prediction > 0.5)
82
+
83
+ return jsonify({
84
+ 'probability': float(prediction),
85
+ 'is_best': is_best
86
+ })
87
+ except Exception as e:
88
+ return jsonify({'error': str(e)}), 500
89
+
90
+ if __name__ == '__main__':
91
+ load_resources()
92
+ app.run(host='0.0.0.0', port=7860, debug=False)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ pandas
2
+ numpy
3
+ tensorflow
4
+ scikit-learn
5
+ matplotlib
6
+ seaborn
7
+ flask
8
+ flask-cors
static/css/style.css ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --primary-color: #6366f1;
3
+ --primary-hover: #4f46e5;
4
+ --bg-dark: #0f172a;
5
+ --glass-bg: rgba(255, 255, 255, 0.05);
6
+ --glass-border: rgba(255, 255, 255, 0.1);
7
+ --text-main: #f8fafc;
8
+ --text-muted: #94a3b8;
9
+ --accent: #f43f5e;
10
+ --success: #10b981;
11
+ }
12
+
13
+ * {
14
+ margin: 0;
15
+ padding: 0;
16
+ box-sizing: border-box;
17
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
18
+ }
19
+
20
+ body {
21
+ background-color: var(--bg-dark);
22
+ color: var(--text-main);
23
+ min-height: 100vh;
24
+ display: flex;
25
+ justify-content: center;
26
+ align-items: center;
27
+ background-image: radial-gradient(circle at 50% 50%, #1e293b 0%, #0f172a 100%);
28
+ }
29
+
30
+ .container {
31
+ width: 90%;
32
+ max-width: 800px;
33
+ padding: 2rem;
34
+ background: var(--glass-bg);
35
+ backdrop-filter: blur(12px);
36
+ border: 1px solid var(--glass-border);
37
+ border-radius: 24px;
38
+ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
39
+ animation: fadeIn 0.8s ease-out;
40
+ }
41
+
42
+ @keyframes fadeIn {
43
+ from {
44
+ opacity: 0;
45
+ transform: translateY(20px);
46
+ }
47
+
48
+ to {
49
+ opacity: 1;
50
+ transform: translateY(0);
51
+ }
52
+ }
53
+
54
+ h1 {
55
+ font-size: 2.5rem;
56
+ margin-bottom: 0.5rem;
57
+ background: linear-gradient(to right, #818cf8, #f472b6);
58
+ -webkit-background-clip: text;
59
+ -webkit-text-fill-color: transparent;
60
+ text-align: center;
61
+ }
62
+
63
+ p.subtitle {
64
+ color: var(--text-muted);
65
+ text-align: center;
66
+ margin-bottom: 2.5rem;
67
+ }
68
+
69
+ .form-group {
70
+ margin-bottom: 1.5rem;
71
+ }
72
+
73
+ label {
74
+ display: block;
75
+ margin-bottom: 0.5rem;
76
+ font-weight: 500;
77
+ color: var(--text-main);
78
+ }
79
+
80
+ textarea,
81
+ input {
82
+ width: 100%;
83
+ padding: 1rem;
84
+ background: rgba(0, 0, 0, 0.2);
85
+ border: 1px solid var(--glass-border);
86
+ border-radius: 12px;
87
+ color: white;
88
+ font-size: 1rem;
89
+ transition: all 0.3s ease;
90
+ }
91
+
92
+ textarea:focus,
93
+ input:focus {
94
+ outline: none;
95
+ border-color: var(--primary-color);
96
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
97
+ }
98
+
99
+ button {
100
+ width: 100%;
101
+ padding: 1rem;
102
+ background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
103
+ border: none;
104
+ border-radius: 12px;
105
+ color: white;
106
+ font-weight: 600;
107
+ font-size: 1.1rem;
108
+ cursor: pointer;
109
+ transition: transform 0.2s, box-shadow 0.2s;
110
+ margin-top: 1rem;
111
+ }
112
+
113
+ button:hover {
114
+ transform: translateY(-2px);
115
+ box-shadow: 0 4px 15px rgba(99, 102, 241, 0.4);
116
+ }
117
+
118
+ button:active {
119
+ transform: translateY(0);
120
+ }
121
+
122
+ .result-container {
123
+ margin-top: 2rem;
124
+ padding: 1.5rem;
125
+ border-radius: 16px;
126
+ background: rgba(255, 255, 255, 0.03);
127
+ border: 1px dashed var(--glass-border);
128
+ display: none;
129
+ }
130
+
131
+ .result-header {
132
+ font-weight: 600;
133
+ margin-bottom: 0.5rem;
134
+ }
135
+
136
+ .score-badge {
137
+ display: inline-block;
138
+ padding: 0.5rem 1rem;
139
+ border-radius: 99px;
140
+ font-weight: 700;
141
+ margin-top: 0.5rem;
142
+ }
143
+
144
+ .score-good {
145
+ background: rgba(16, 185, 129, 0.2);
146
+ color: #10b981;
147
+ }
148
+
149
+ .score-bad {
150
+ background: rgba(244, 63, 94, 0.2);
151
+ color: #f43f5e;
152
+ }
153
+
154
+ .loader {
155
+ width: 24px;
156
+ height: 24px;
157
+ border: 3px solid #FFF;
158
+ border-bottom-color: transparent;
159
+ border-radius: 50%;
160
+ display: inline-block;
161
+ box-sizing: border-box;
162
+ animation: rotation 1s linear infinite;
163
+ display: none;
164
+ vertical-align: middle;
165
+ margin-right: 10px;
166
+ }
167
+
168
+ .tabs {
169
+ display: flex;
170
+ gap: 1rem;
171
+ margin-bottom: 2rem;
172
+ justify-content: center;
173
+ }
174
+
175
+ .tab {
176
+ padding: 0.75rem 1.5rem;
177
+ background: rgba(255, 255, 255, 0.05);
178
+ border-radius: 12px;
179
+ cursor: pointer;
180
+ transition: all 0.3s ease;
181
+ border: 1px solid var(--glass-border);
182
+ color: var(--text-muted);
183
+ }
184
+
185
+ .tab.active {
186
+ background: var(--primary-color);
187
+ color: white;
188
+ border-color: var(--primary-color);
189
+ }
190
+
191
+ .view {
192
+ display: none;
193
+ }
194
+
195
+ .view.active {
196
+ display: block;
197
+ }
198
+
199
+ .dashboard-grid {
200
+ display: grid;
201
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
202
+ gap: 1.5rem;
203
+ margin-top: 1rem;
204
+ }
205
+
206
+ .stat-card {
207
+ background: rgba(255, 255, 255, 0.03);
208
+ padding: 1.5rem;
209
+ border-radius: 16px;
210
+ border: 1px solid var(--glass-border);
211
+ text-align: center;
212
+ }
213
+
214
+ .stat-value {
215
+ font-size: 1.5rem;
216
+ font-weight: 700;
217
+ margin-top: 0.5rem;
218
+ color: var(--primary-color);
219
+ }
220
+
221
+ .engine-list {
222
+ margin-top: 2rem;
223
+ }
224
+
225
+ .engine-item {
226
+ display: flex;
227
+ justify-content: space-between;
228
+ padding: 1rem;
229
+ border-bottom: 1px solid var(--glass-border);
230
+ }
231
+
232
+ .engine-item:last-child {
233
+ border-bottom: none;
234
+ }
235
+
236
+ @keyframes rotation {
237
+ 0% {
238
+ transform: rotate(0deg);
239
+ }
240
+
241
+ 100% {
242
+ transform: rotate(360deg);
243
+ }
244
+ }
templates/index.html ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>AI Chatbot Performance Analyzer</title>
8
+ <link rel="stylesheet" href="/static/css/style.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
10
+ </head>
11
+
12
+ <body>
13
+ <div class="container">
14
+ <h1>Advanced Chatbot Performance</h1>
15
+ <p class="subtitle">Multi-context Evaluation with Attention LSTM</p>
16
+
17
+ <div id="status-bar"
18
+ style="margin-bottom: 1rem; text-align: center; font-size: 0.85rem; color: #fbbf24; background: rgba(251, 191, 36, 0.1); padding: 0.5rem; border-radius: 8px; border: 1px solid rgba(251, 191, 36, 0.2);">
19
+ ⚠️ Model Initialization in Progress... (Epoch 1/2)
20
+ </div>
21
+
22
+ <div class="tabs">
23
+ <div class="tab active" onclick="switchTab('analyzer')">Analyzer</div>
24
+ <div class="tab" onclick="switchTab('dashboard')">Analytics Dashboard</div>
25
+ </div>
26
+
27
+ <!-- Analyzer View -->
28
+ <div id="analyzer-view" class="view active">
29
+ <div class="form-group">
30
+ <label for="facts">Related Context / Facts</label>
31
+ <textarea id="facts" rows="3" placeholder="Paste the knowledge base or facts here..."></textarea>
32
+ </div>
33
+
34
+ <div class="form-group">
35
+ <label for="question">User Question</label>
36
+ <textarea id="question" rows="2" placeholder="Enter the user question..."></textarea>
37
+ </div>
38
+
39
+ <div class="form-group">
40
+ <label for="response">Chatbot Response</label>
41
+ <textarea id="response" rows="3" placeholder="Enter the chatbot response..."></textarea>
42
+ </div>
43
+
44
+ <button id="analyze-btn">
45
+ <span class="loader" id="loader"></span>
46
+ Perform Deep Analysis
47
+ </button>
48
+
49
+ <div id="result" class="result-container">
50
+ <div class="result-header">Expert Verdict:</div>
51
+ <div id="result-text"></div>
52
+ <div id="score-badge" class="score-badge"></div>
53
+ <div id="probability" style="margin-top: 1rem; font-size: 0.9rem; color: var(--text-muted);"></div>
54
+ </div>
55
+ </div>
56
+
57
+ <!-- Dashboard View -->
58
+ <div id="dashboard-view" class="view">
59
+ <h2 style="margin-bottom: 1rem;">Dataset Insights</h2>
60
+ <div class="dashboard-grid">
61
+ <div class="stat-card">
62
+ <div>Total Queries</div>
63
+ <div class="stat-value" id="total-queries">40,152</div>
64
+ </div>
65
+ <div class="stat-card">
66
+ <div>Overall Accuracy</div>
67
+ <div class="stat-value" id="overall-quality">31.4%</div>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="engine-list">
72
+ <h3 style="margin-bottom: 0.5rem;">Engine Performance Breakdown</h3>
73
+ <div class="engine-item">
74
+ <span>Openbook Performance</span>
75
+ <span style="color: var(--success)">67.3% Top Responses</span>
76
+ </div>
77
+ <div class="engine-item">
78
+ <span>Dialogflow Performance</span>
79
+ <span style="color: #6366f1">24.2% Top Responses</span>
80
+ </div>
81
+ <div class="engine-item">
82
+ <span>Watson Performance</span>
83
+ <span style="color: var(--accent)">19.3% Top Responses</span>
84
+ </div>
85
+ <div class="engine-item">
86
+ <span>Rasa Performance</span>
87
+ <span style="color: var(--accent)">14.6% Top Responses</span>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+
93
+ <script>
94
+ // Check model status on load and every 30 seconds
95
+ async function checkStatus() {
96
+ try {
97
+ const res = await fetch('/predict', {
98
+ method: 'POST',
99
+ headers: { 'Content-Type': 'application/json' },
100
+ body: JSON.stringify({ ping: true })
101
+ });
102
+ if (res.ok) {
103
+ const statusBar = document.getElementById('status-bar');
104
+ statusBar.style.color = '#10b981';
105
+ statusBar.style.background = 'rgba(16, 185, 129, 0.1)';
106
+ statusBar.style.borderColor = 'rgba(16, 185, 129, 0.2)';
107
+ statusBar.innerText = '✅ Advanced Intelligence Engine Active';
108
+ setTimeout(() => statusBar.style.display = 'none', 5000);
109
+ }
110
+ } catch (e) { }
111
+ }
112
+ checkStatus();
113
+ const statusInterval = setInterval(() => {
114
+ const statusBar = document.getElementById('status-bar');
115
+ if (statusBar && statusBar.style.display !== 'none') {
116
+ checkStatus();
117
+ } else {
118
+ clearInterval(statusInterval);
119
+ }
120
+ }, 15000);
121
+
122
+ function switchTab(tab) {
123
+
124
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
125
+ document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
126
+
127
+ if (tab === 'analyzer') {
128
+ document.querySelector('.tab:nth-child(1)').classList.add('active');
129
+ document.getElementById('analyzer-view').classList.add('active');
130
+ } else {
131
+ document.querySelector('.tab:nth-child(2)').classList.add('active');
132
+ document.getElementById('dashboard-view').classList.add('active');
133
+ }
134
+ }
135
+
136
+ document.getElementById('analyze-btn').addEventListener('click', async () => {
137
+ const facts = document.getElementById('facts').value;
138
+ const question = document.getElementById('question').value;
139
+ const response = document.getElementById('response').value;
140
+ const loader = document.getElementById('loader');
141
+ const resultDiv = document.getElementById('result');
142
+ const resultText = document.getElementById('result-text');
143
+ const scoreBadge = document.getElementById('score-badge');
144
+ const probDiv = document.getElementById('probability');
145
+
146
+ if (!question || !response) {
147
+ alert('Please fill in the question and response.');
148
+ return;
149
+ }
150
+
151
+ loader.style.display = 'inline-block';
152
+ document.getElementById('analyze-btn').disabled = true;
153
+ resultDiv.style.display = 'none';
154
+
155
+ try {
156
+ const res = await fetch('/predict', {
157
+ method: 'POST',
158
+ headers: { 'Content-Type': 'application/json' },
159
+ body: JSON.stringify({ facts, question, response })
160
+ });
161
+
162
+ const data = await res.json();
163
+
164
+ if (!res.ok) {
165
+ if (res.status === 503) {
166
+ alert(data.error);
167
+ } else {
168
+ alert('Analysis Error: ' + (data.error || 'Server error'));
169
+ }
170
+ return;
171
+ }
172
+
173
+ resultDiv.style.display = 'block';
174
+ if (data.is_best) {
175
+ resultText.innerText = "Advanced analysis confirms this is a high-fidelity response.";
176
+ scoreBadge.innerText = "OPTIMIZED";
177
+ scoreBadge.className = "score-badge score-good";
178
+ } else {
179
+ resultText.innerText = "Analysis suggests potential inaccuracies or linguistic flaws.";
180
+ scoreBadge.innerText = "SUB-OPTIMAL";
181
+ scoreBadge.className = "score-badge score-bad";
182
+ }
183
+
184
+ probDiv.innerText = `Attention Confidence: ${(data.probability * 100).toFixed(2)}%`;
185
+
186
+ } catch (err) {
187
+ alert('Analysis failed. Ensure server is running.');
188
+ } finally {
189
+ loader.style.display = 'none';
190
+ document.getElementById('analyze-btn').disabled = false;
191
+ }
192
+ });
193
+ </script>
194
+ </body>
195
+
196
+ </html>