shiva9876 commited on
Commit
23d782b
·
verified ·
1 Parent(s): 17e2dfe

Upload 3 files

Browse files
Files changed (3) hide show
  1. ui/app.js +157 -0
  2. ui/index.html +41 -0
  3. ui/style.css +207 -0
ui/app.js ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const API_BASE_URL = 'http://127.0.0.1:7861';
2
+
3
+ const promptInput = document.getElementById('promptInput');
4
+ const responseTypeSelect = document.getElementById('responseTypeSelect');
5
+ const generateBtn = document.getElementById('generateBtn');
6
+ const chatWindow = document.getElementById('chat-window');
7
+ const newSessionBtn = document.getElementById('newSessionBtn');
8
+ const clearHistoryBtn = document.getElementById('clearHistoryBtn');
9
+
10
+ let currentSessionId = localStorage.getItem('langchainChatSessionId') || crypto.randomUUID();
11
+ let isLoading = false;
12
+
13
+ const updateSessionId = (newId) => {
14
+ currentSessionId = newId;
15
+ localStorage.setItem('langchainChatSessionId', currentSessionId);
16
+ console.log(`Session ID set to: ${currentSessionId}`);
17
+ };
18
+
19
+ const escapeHtml = (text) => {
20
+ if (!text) return '';
21
+ const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
22
+ return text.replace(/[&<>"']/g, m => map[m]);
23
+ };
24
+
25
+ const scrollToBottom = () => {
26
+ chatWindow.scrollTop = chatWindow.scrollHeight;
27
+ };
28
+
29
+ const displayUserMessage = (text) => {
30
+ const messageEl = document.createElement('div');
31
+ messageEl.className = 'message-bubble user';
32
+ messageEl.textContent = text;
33
+ chatWindow.appendChild(messageEl);
34
+ scrollToBottom();
35
+ };
36
+
37
+ const displayBotMessage = (data) => {
38
+ const messageEl = document.createElement('div');
39
+ messageEl.className = 'message-bubble bot';
40
+
41
+ let content = '';
42
+ if (data.explanation) {
43
+ content += `<div class="content-block"><h3>Explanation</h3>${escapeHtml(data.explanation)}</div>`;
44
+ }
45
+ if (data.generated_code) {
46
+ content += `<div class="content-block"><h3>Code</h3><pre>${escapeHtml(data.generated_code)}</pre></div>`;
47
+ }
48
+ if (!data.explanation && !data.generated_code && data.response) {
49
+ content += `<div class="content-block">${escapeHtml(data.response)}</div>`;
50
+ }
51
+
52
+ messageEl.innerHTML = content;
53
+ chatWindow.appendChild(messageEl);
54
+ scrollToBottom();
55
+ };
56
+
57
+ const toggleTypingIndicator = (show) => {
58
+ let indicator = document.getElementById('typing-indicator');
59
+ if (show) {
60
+ if (!indicator) {
61
+ indicator = document.createElement('div');
62
+ indicator.id = 'typing-indicator';
63
+ indicator.className = 'message-bubble bot typing-indicator';
64
+ indicator.innerHTML = '<span></span><span></span><span></span>';
65
+ chatWindow.appendChild(indicator);
66
+ scrollToBottom();
67
+ }
68
+ } else {
69
+ if (indicator) {
70
+ indicator.remove();
71
+ }
72
+ }
73
+ };
74
+
75
+ const generateResponse = async () => {
76
+ const prompt = promptInput.value.trim();
77
+ if (!prompt || isLoading) return;
78
+
79
+ isLoading = true;
80
+ generateBtn.disabled = true;
81
+
82
+ displayUserMessage(prompt);
83
+ promptInput.value = '';
84
+ promptInput.style.height = 'auto'; // Reset height
85
+ toggleTypingIndicator(true);
86
+
87
+ try {
88
+ const response = await fetch(`${API_BASE_URL}/generate/`, {
89
+ method: 'POST',
90
+ headers: { 'Content-Type': 'application/json' },
91
+ body: JSON.stringify({
92
+ prompt,
93
+ session_id: currentSessionId,
94
+ response_type: responseTypeSelect.value,
95
+ }),
96
+ });
97
+
98
+ if (!response.ok) {
99
+ const errorData = await response.json();
100
+ throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
101
+ }
102
+
103
+ const data = await response.json();
104
+ displayBotMessage(data);
105
+
106
+ } catch (error) {
107
+ displayBotMessage({ explanation: `Error: ${error.message}` });
108
+ } finally {
109
+ isLoading = false;
110
+ generateBtn.disabled = false;
111
+ toggleTypingIndicator(false);
112
+ }
113
+ };
114
+
115
+ const newSession = () => {
116
+ updateSessionId(crypto.randomUUID());
117
+ chatWindow.innerHTML = '';
118
+ // You might want a system message here
119
+ displayBotMessage({response: "New session started. How can I help you today?"});
120
+ };
121
+
122
+ const clearHistory = async () => {
123
+ try {
124
+ await fetch(`${API_BASE_URL}/clear_history/`, {
125
+ method: 'POST',
126
+ headers: { 'Content-Type': 'application/json' },
127
+ body: JSON.stringify({ session_id: currentSessionId }),
128
+ });
129
+ chatWindow.innerHTML = '';
130
+ displayBotMessage({response: "Conversation history for this session has been cleared."});
131
+ } catch (error) {
132
+ displayBotMessage({ explanation: `Error clearing history: ${error.message}` });
133
+ }
134
+ };
135
+
136
+ // Event Listeners
137
+ generateBtn.addEventListener('click', generateResponse);
138
+ promptInput.addEventListener('keydown', (e) => {
139
+ if (e.key === 'Enter' && !e.shiftKey) {
140
+ e.preventDefault();
141
+ generateResponse();
142
+ }
143
+ });
144
+
145
+ // Auto-resize textarea
146
+ promptInput.addEventListener('input', () => {
147
+ promptInput.style.height = 'auto';
148
+ promptInput.style.height = `${promptInput.scrollHeight}px`;
149
+ });
150
+
151
+ newSessionBtn.addEventListener('click', newSession);
152
+ clearHistoryBtn.addEventListener('click', clearHistory);
153
+
154
+ document.addEventListener('DOMContentLoaded', () => {
155
+ updateSessionId(currentSessionId);
156
+ displayBotMessage({response: "Welcome! I'm ready to assist you."});
157
+ });
ui/index.html ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>LangChain AI Chatbot</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
9
+ <link rel="stylesheet" href="style.css">
10
+ </head>
11
+ <body>
12
+ <div class="chat-container">
13
+ <header class="chat-header">
14
+ <h1>AI Chatbot</h1>
15
+ <div class="header-controls">
16
+ <select id="responseTypeSelect" class="bg-tertiary border border-primary text-primary text-sm rounded-md focus:ring-accent-user focus:border-accent-user block w-full p-2" style="background-color: var(--bg-tertiary); border-color: var(--border-primary);">
17
+ <option value="both">Explain & Code</option>
18
+ <option value="conversation">Conversation</option>
19
+ <option value="code">Code Only</option>
20
+ <option value="explanation">Explanation Only</option>
21
+ </select>
22
+ <button id="newSessionBtn" class="btn-icon" title="New Session">
23
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0011.667 0l3.181-3.183m-4.991-2.691V5.25a2.25 2.25 0 00-2.25-2.25L12 3m0 0l-3.181 3.183a8.25 8.25 0 000 11.667l3.181 3.183" /></svg>
24
+ </button>
25
+ <button id="clearHistoryBtn" class="btn-icon" title="Clear History">
26
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
27
+ </button>
28
+ </div>
29
+ </header>
30
+ <main id="chat-window"></main>
31
+ <footer class="chat-input-area">
32
+ <textarea id="promptInput" rows="1" placeholder="Ask anything..."></textarea>
33
+ <button id="generateBtn" class="btn-send">
34
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" /></svg>
35
+ </button>
36
+ </footer>
37
+ </div>
38
+ <div id="errorMessage" style="display: none;"></div>
39
+ <script src="app.js"></script>
40
+ </body>
41
+ </html>
ui/style.css ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg-primary: #0D1117;
3
+ --bg-secondary: #161B22;
4
+ --bg-tertiary: #21262D;
5
+ --border-primary: #30363D;
6
+ --text-primary: #C9D1D9;
7
+ --text-secondary: #8B949E;
8
+ --accent-user: #2F81F7;
9
+ --accent-user-hover: #58A6FF;
10
+ --font-family-sans: 'Inter', sans-serif;
11
+ --font-family-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
12
+ }
13
+
14
+ body {
15
+ font-family: var(--font-family-sans);
16
+ background-color: var(--bg-primary);
17
+ color: var(--text-primary);
18
+ display: flex;
19
+ justify-content: center;
20
+ align-items: center;
21
+ height: 100vh;
22
+ padding: 1rem;
23
+ }
24
+
25
+ .chat-container {
26
+ background-color: var(--bg-secondary);
27
+ border: 1px solid var(--border-primary);
28
+ border-radius: 0.75rem;
29
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
30
+ width: 100%;
31
+ max-width: 800px;
32
+ height: 90vh;
33
+ display: flex;
34
+ flex-direction: column;
35
+ overflow: hidden;
36
+ }
37
+
38
+ .chat-header {
39
+ padding: 0.75rem 1.5rem;
40
+ border-bottom: 1px solid var(--border-primary);
41
+ display: flex;
42
+ justify-content: space-between;
43
+ align-items: center;
44
+ flex-shrink: 0;
45
+ }
46
+
47
+ .chat-header h1 {
48
+ font-size: 1.25rem;
49
+ font-weight: 600;
50
+ }
51
+
52
+ .header-controls {
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 0.75rem;
56
+ }
57
+
58
+ #chat-window {
59
+ flex-grow: 1;
60
+ padding: 1.5rem;
61
+ overflow-y: auto;
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 1rem;
65
+ }
66
+
67
+ .message-bubble {
68
+ max-width: 75%;
69
+ padding: 0.75rem 1.25rem;
70
+ border-radius: 1.25rem;
71
+ line-height: 1.6;
72
+ word-wrap: break-word;
73
+ }
74
+
75
+ .message-bubble.user {
76
+ background-color: var(--accent-user);
77
+ color: white;
78
+ align-self: flex-end;
79
+ border-bottom-right-radius: 0.375rem;
80
+ }
81
+
82
+ .message-bubble.bot {
83
+ background-color: var(--bg-tertiary);
84
+ color: var(--text-primary);
85
+ align-self: flex-start;
86
+ border-bottom-left-radius: 0.375rem;
87
+ }
88
+
89
+ .bot .content-block {
90
+ border-top: 1px solid var(--border-primary);
91
+ margin-top: 0.75rem;
92
+ padding-top: 0.75rem;
93
+ }
94
+
95
+ .bot .content-block:first-child {
96
+ margin-top: 0;
97
+ padding-top: 0;
98
+ border-top: none;
99
+ }
100
+
101
+ .bot h3 {
102
+ font-size: 0.75rem;
103
+ text-transform: uppercase;
104
+ color: var(--text-secondary);
105
+ margin-bottom: 0.5rem;
106
+ font-weight: 600;
107
+ }
108
+
109
+ .bot pre {
110
+ font-family: var(--font-family-mono);
111
+ font-size: 0.9rem;
112
+ background-color: var(--bg-primary);
113
+ padding: 0.75rem;
114
+ border-radius: 0.5rem;
115
+ white-space: pre-wrap;
116
+ word-break: break-all;
117
+ }
118
+
119
+ .typing-indicator {
120
+ display: flex;
121
+ gap: 0.25rem;
122
+ align-items: center;
123
+ padding: 0.75rem 1.25rem;
124
+ }
125
+ .typing-indicator span {
126
+ width: 8px;
127
+ height: 8px;
128
+ border-radius: 50%;
129
+ background-color: var(--text-secondary);
130
+ animation: bounce 1.4s infinite ease-in-out both;
131
+ }
132
+ .typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
133
+ .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
134
+ @keyframes bounce {
135
+ 0%, 80%, 100% { transform: scale(0); }
136
+ 40% { transform: scale(1.0); }
137
+ }
138
+
139
+
140
+ .chat-input-area {
141
+ padding: 1rem 1.5rem;
142
+ border-top: 1px solid var(--border-primary);
143
+ display: flex;
144
+ gap: 1rem;
145
+ align-items: center;
146
+ }
147
+
148
+ .chat-input-area textarea {
149
+ flex-grow: 1;
150
+ background-color: var(--bg-tertiary);
151
+ border: 1px solid var(--border-primary);
152
+ border-radius: 1.5rem;
153
+ padding: 0.75rem 1.25rem;
154
+ color: var(--text-primary);
155
+ resize: none;
156
+ outline: none;
157
+ transition: all 0.2s;
158
+ }
159
+ .chat-input-area textarea:focus {
160
+ border-color: var(--accent-user);
161
+ box-shadow: 0 0 0 3px rgba(47, 129, 247, 0.3);
162
+ }
163
+
164
+ .btn-send {
165
+ flex-shrink: 0;
166
+ width: 48px;
167
+ height: 48px;
168
+ border-radius: 50%;
169
+ background-color: var(--accent-user);
170
+ color: white;
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: center;
174
+ cursor: pointer;
175
+ transition: all 0.2s;
176
+ border: none;
177
+ }
178
+ .btn-send:hover:not(:disabled) {
179
+ background-color: var(--accent-user-hover);
180
+ }
181
+ .btn-send:disabled {
182
+ background-color: var(--text-secondary);
183
+ cursor: not-allowed;
184
+ }
185
+ .btn-send svg {
186
+ width: 24px;
187
+ height: 24px;
188
+ }
189
+
190
+ /* Utility for session management buttons */
191
+ .btn-icon {
192
+ background: none;
193
+ border: none;
194
+ color: var(--text-secondary);
195
+ cursor: pointer;
196
+ padding: 0.5rem;
197
+ border-radius: 50%;
198
+ transition: all 0.2s;
199
+ }
200
+ .btn-icon:hover {
201
+ background-color: var(--bg-tertiary);
202
+ color: var(--text-primary);
203
+ }
204
+ .btn-icon svg { width: 20px; height: 20px; }
205
+
206
+ /* Hiding original elements not needed in chat UI */
207
+ #historyContainer, #rawResponseDisplay, #getHistoryBtn { display: none !important; }