ArnoChen commited on
Commit
8facc80
·
1 Parent(s): f1e780e

remove webui_depricated

Browse files
lightrag/api/webui_depricated/static/__init__.py DELETED
File without changes
lightrag/api/webui_depricated/static/css/__init__.py DELETED
File without changes
lightrag/api/webui_depricated/static/css/graph.css DELETED
@@ -1,86 +0,0 @@
1
- /* css/lightrag.css */
2
-
3
- /*Modal box style*/
4
- .modal {
5
- display: none;
6
- position: fixed;
7
- top: 0;
8
- left: 0;
9
- width: 100%;
10
- height: 100%;
11
- background-color: rgba(0, 0, 0, 0.5);
12
- justify-content: center;
13
- align-items: center;
14
- z-index: 1000;
15
- }
16
-
17
- .modal-content {
18
- background-color: var(--surface);
19
- padding: 1.5rem;
20
- border-radius: 8px;
21
- width: 80%;
22
- max-width: 1200px;
23
- box-shadow: var(--shadow);
24
- }
25
-
26
- .modal-header {
27
- display: flex;
28
- justify-content: space-between;
29
- align-items: center;
30
- margin-bottom: 1rem;
31
- }
32
-
33
- .modal-body {
34
- margin-bottom: 1rem;
35
- }
36
-
37
- .modal-footer {
38
- text-align: right;
39
- }
40
-
41
- .btn-close {
42
- background: none;
43
- border: none;
44
- font-size: 1.5rem;
45
- cursor: pointer;
46
- color: var(--text-secondary);
47
- }
48
-
49
- .btn-close:hover {
50
- color: var(--text-primary);
51
- }
52
-
53
- /* graph style */
54
- .node {
55
- cursor: pointer;
56
- fill: var(--primary);
57
- stroke: var(--surface);
58
- stroke-width: 2px;
59
- }
60
-
61
- .node:hover {
62
- fill: var(--secondary);
63
- }
64
-
65
- .link {
66
- stroke: var(--text-secondary);
67
- stroke-width: 2px;
68
- }
69
-
70
- .label {
71
- font-size: 12px;
72
- fill: var(--text-primary);
73
- pointer-events: none;
74
- }
75
-
76
- /* edge style */
77
- .link {
78
- stroke: #999;
79
- stroke-width: 2px;
80
- stroke-opacity: 0.8;
81
- }
82
-
83
- /* Arrow color matches edge color */
84
- #arrow path {
85
- fill: #999 !important;
86
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lightrag/api/webui_depricated/static/css/lightrag.css DELETED
@@ -1,385 +0,0 @@
1
-
2
- * {
3
- box-sizing: border-box;
4
- margin: 0;
5
- padding: 0;
6
- }
7
-
8
- body {
9
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
10
- line-height: 1.6;
11
- background-color: var(--background);
12
- color: var(--text-primary);
13
- }
14
-
15
- /* main container */
16
- .app-container {
17
- max-width: 1600px;
18
- margin: 0 auto;
19
- padding: 2rem;
20
- display: grid;
21
- grid-template-columns: 240px 1fr;
22
- gap: 2rem;
23
- min-height: 100vh;
24
- }
25
-
26
- /* Navigation sidebar */
27
- .nav-panel {
28
- position: sticky;
29
- top: 2rem;
30
- height: fit-content;
31
- background: var(--surface);
32
- border-radius: 12px;
33
- padding: 1.5rem;
34
- box-shadow: var(--shadow);
35
- }
36
-
37
- .nav-title {
38
- font-size: 1.25rem;
39
- font-weight: 600;
40
- color: var(--primary);
41
- padding-bottom: 1rem;
42
- margin-bottom: 1rem;
43
- border-bottom: 1px solid var(--border);
44
- }
45
-
46
- /* Main content area */
47
- .main-content {
48
- display: grid;
49
- gap: 1.5rem;
50
- align-content: start;
51
- }
52
-
53
- /* Card based module */
54
- .card {
55
- background: var(--surface);
56
- border-radius: 12px;
57
- padding: 1.5rem;
58
- box-shadow: var(--shadow);
59
- transition: transform 0.2s ease;
60
- }
61
-
62
- .card:hover {
63
- transform: translateY(-2px);
64
- }
65
-
66
- .card-title {
67
- font-size: 1.125rem;
68
- font-weight: 600;
69
- margin-bottom: 1rem;
70
- color: var(--primary);
71
- }
72
-
73
- /* File upload area */
74
- .file-dropzone {
75
- border: 2px dashed var(--border);
76
- border-radius: 8px;
77
- padding: 2rem;
78
- text-align: center;
79
- transition: all 0.3s ease;
80
- background: rgba(241, 245, 249, 0.5);
81
- }
82
-
83
- .file-dropzone.active {
84
- border-color: var(--primary);
85
- background: rgba(79, 70, 229, 0.05);
86
- }
87
-
88
-
89
- .btn {
90
- display: inline-flex;
91
- align-items: center;
92
- gap: 0.5rem;
93
- padding: 0.75rem 1.5rem;
94
- border: none;
95
- border-radius: 8px;
96
- font-weight: 500;
97
- cursor: pointer;
98
- transition: all 0.2s ease;
99
- }
100
-
101
- .btn-primary {
102
- background: var(--primary);
103
- color: white;
104
- }
105
-
106
- .btn-primary:hover {
107
- background: #4338CA;
108
- }
109
-
110
- .btn-secondary {
111
- background: var(--secondary);
112
- color: white;
113
- }
114
-
115
- .btn-secondary:hover {
116
- background: #059669;
117
- }
118
-
119
- .input-field {
120
- width: 100%;
121
- padding: 0.875rem;
122
- border: 1px solid var(--border);
123
- border-radius: 8px;
124
- font-size: 1rem;
125
- transition: border-color 0.2s ease;
126
- }
127
-
128
- .input-field:focus {
129
- outline: none;
130
- border-color: var(--primary);
131
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
132
- }
133
-
134
-
135
- @media (max-width: 768px) {
136
- .app-container {
137
- grid-template-columns: 1fr;
138
- padding: 1rem;
139
- }
140
-
141
- .nav-panel {
142
- position: static;
143
- margin-bottom: 1.5rem;
144
- }
145
-
146
- .btn.active {
147
- box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
148
- transform: translateY(1px);
149
- }
150
- }
151
-
152
- .toast {
153
- position: fixed;
154
- bottom: 20px;
155
- right: 20px;
156
- padding: 12px 24px;
157
- border-radius: 8px;
158
- background: var(--surface);
159
- box-shadow: var(--shadow);
160
- z-index: 1000;
161
- }
162
-
163
- .toast.success {
164
- background: var(--secondary);
165
- color: white;
166
- }
167
-
168
- .toast.error {
169
- background: #EF4444;
170
- color: white;
171
- }
172
-
173
- .loading {
174
- position: relative;
175
- opacity: 0.6;
176
- }
177
-
178
- .loading::after {
179
- content: "···";
180
- animation: loading 1s infinite;
181
- }
182
-
183
- @keyframes loading {
184
- 0% {
185
- content: "·";
186
- }
187
- 33% {
188
- content: "··";
189
- }
190
- 66% {
191
- content: "···";
192
- }
193
- }
194
-
195
- .text-upload-form {
196
- display: grid;
197
- gap: 1.5rem;
198
- }
199
-
200
- .form-group label {
201
- display: block;
202
- margin-bottom: 0.5rem;
203
- color: var(--text-primary);
204
- font-weight: 500;
205
- }
206
-
207
- .action-bar {
208
- display: flex;
209
- align-items: center;
210
- gap: 1rem;
211
- margin-top: 1rem;
212
- }
213
-
214
- .status-indicator {
215
- padding: 0.5rem 1rem;
216
- border-radius: 6px;
217
- font-size: 0.9em;
218
- transition: all 0.3s ease;
219
- }
220
-
221
- .status-indicator.success {
222
- background: var(--secondary);
223
- color: white;
224
- }
225
-
226
- .status-indicator.error {
227
- background: #ef4444;
228
- color: white;
229
- }
230
-
231
- .status-grid {
232
- display: grid;
233
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
234
- gap: 1.5rem;
235
- margin-top: 1rem;
236
- }
237
-
238
- .status-card {
239
- background: var(--surface);
240
- border-radius: 12px;
241
- padding: 1.5rem;
242
- box-shadow: var(--shadow);
243
- }
244
-
245
- .status-header {
246
- display: flex;
247
- align-items: center;
248
- gap: 0.75rem;
249
- margin-bottom: 1rem;
250
- }
251
-
252
- .status-icon {
253
- font-size: 1.5rem;
254
- color: var(--primary);
255
- }
256
-
257
- .progress-container {
258
- margin-top: 1rem;
259
- }
260
-
261
- .progress-labels {
262
- display: flex;
263
- justify-content: space-between;
264
- margin-top: 0.5rem;
265
- font-size: 0.875rem;
266
- color: var(--text-secondary);
267
- }
268
-
269
- .config-list {
270
- display: grid;
271
- grid-template-columns: max-content 1fr;
272
- gap: 0.75rem 1.5rem;
273
- margin-top: 1rem;
274
- }
275
-
276
- .config-list dt {
277
- font-weight: 500;
278
- color: var(--text-secondary);
279
- }
280
-
281
- .config-list dd {
282
- margin: 0;
283
- color: var(--text-primary);
284
- }
285
-
286
- .directory-list {
287
- margin-top: 1rem;
288
- }
289
-
290
- .directory-item {
291
- display: flex;
292
- gap: 0.5rem;
293
- margin-bottom: 0.5rem;
294
- }
295
-
296
- .directory-label {
297
- font-weight: 500;
298
- color: var(--text-secondary);
299
- flex-shrink: 0;
300
- }
301
-
302
- .directory-path {
303
- color: var(--text-primary);
304
- word-break: break-all;
305
- }
306
-
307
- .status-badge {
308
- display: inline-block;
309
- padding: 0.5rem 1rem;
310
- border-radius: 20px;
311
- font-size: 0.875rem;
312
- font-weight: 500;
313
- margin-top: 1rem;
314
- }
315
-
316
- .health-status .status-badge {
317
- background: rgba(16, 185, 129, 0.1);
318
- color: #10B981;
319
- border: 1px solid rgba(16, 185, 129, 0.2);
320
- }
321
-
322
- .status-badge.loading {
323
- background: rgba(79, 70, 229, 0.1);
324
- color: var(--primary);
325
- }
326
-
327
- .status-badge.error {
328
- background: rgba(239, 68, 68, 0.1);
329
- color: #EF4444;
330
- }
331
-
332
- .label-container {
333
- max-height: 60vh;
334
- overflow-y: auto;
335
- border: 1px solid var(--border);
336
- border-radius: 8px;
337
- padding: 1rem;
338
- }
339
-
340
- .label-item {
341
- display: flex;
342
- align-items: center;
343
- justify-content: space-between;
344
- padding: 0.75rem;
345
- margin-bottom: 0.5rem;
346
- background: var(--surface);
347
- border-radius: 6px;
348
- box-shadow: var(--shadow);
349
- }
350
-
351
- .label-item:hover {
352
- transform: translateX(4px);
353
- transition: transform 0.2s ease;
354
- }
355
-
356
- .label-actions {
357
- display: flex;
358
- gap: 0.5rem;
359
- }
360
-
361
- .toast {
362
- position: fixed;
363
- bottom: 2rem;
364
- left: 50%;
365
- transform: translateX(-50%);
366
- padding: 0.75rem 1.5rem;
367
- border-radius: 999px;
368
- font-size: 0.9rem;
369
- z-index: 1000;
370
- }
371
-
372
- .toast-success {
373
- background: var(--secondary);
374
- color: white;
375
- }
376
-
377
- .toast-info {
378
- background: var(--primary);
379
- color: white;
380
- }
381
-
382
- .toast-error {
383
- background: #EF4444;
384
- color: white;
385
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lightrag/api/webui_depricated/static/index.html DELETED
@@ -1,291 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>LightRAG</title>
7
- <style>
8
- :root {
9
- --primary: #4F46E5;
10
- --secondary: #10B981;
11
- --background: #F8FAFC;
12
- --surface: #FFFFFF;
13
- --text-primary: #1E293B;
14
- --text-secondary: #64748B;
15
- --border: #E2E8F0;
16
- --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
17
- }
18
- </style>
19
- <link rel="stylesheet" type="text/css" href="css/lightrag.css">
20
- <link rel="stylesheet" type="text/css" href="css/graph.css">
21
- </head>
22
- <body>
23
- <div class="app-container">
24
- <nav class="nav-panel">
25
- <h2 class="nav-title">LightRAG</h2>
26
- <div class="nav-menu">
27
- <button class="btn btn-primary" style="width: 100%; margin-bottom: 1rem;"
28
- onclick="showSection('documents')">
29
- 📁 DOC MANAGE
30
- </button>
31
- <button class="btn btn-primary" style="width: 100%; margin-bottom: 1rem;"
32
- onclick="showSection('text-upload')">
33
- 📝 TEXT UPLOAD
34
- </button>
35
-
36
- <button class="btn btn-primary" style="width: 100%; margin-bottom: 1rem;" onclick="showSection('query')">
37
- 🔍 GRAPH SEARCH
38
- </button>
39
- <button class="btn btn-primary" style="width: 100%; margin-bottom: 1rem;"
40
- onclick="showSection('label-management'); loadLabels()">
41
- 🏷️ GRAPH MANAGE
42
- </button>
43
- <button class="btn btn-secondary" style="width: 100%;" onclick="showSection('status')">
44
- 📊 SYSTEM STATUS
45
- </button>
46
-
47
- </div>
48
- </nav>
49
-
50
- <main class="main-content">
51
- <section id="documents" class="card">
52
- <h3 class="card-title">DOC MANAGE</h3>
53
- <div class="file-dropzone" id="dropzone">
54
- <input type="file" id="fileInput" hidden multiple>
55
- <p>Drap file</p>
56
- <button class="btn btn-primary" onclick="document.getElementById('fileInput').click()">
57
- 📤 select file
58
- </button>
59
- <div class="file-list" style="margin-top: 1rem;"></div>
60
- <div class="status-indicator" id="fileUploadStatus"></div>
61
- </div>
62
- </section>
63
-
64
- <section id="text-upload" class="card" style="display: none;">
65
- <h3 class="card-title">TEXT UPLOAD</h3>
66
- <div class="text-upload-form">
67
- <div class="form-group">
68
- <label for="textDescription">Title(optional)</label>
69
- <input
70
- type="text"
71
- id="textDescription"
72
- class="input-field"
73
- placeholder="Please enter a text title..."
74
- >
75
- </div>
76
- <div class="form-group">
77
- <label for="textContent">TEXT CONTENT</label>
78
- <textarea
79
- id="textContent"
80
- class="input-field"
81
- placeholder="lease enter a text content..."
82
- rows="8"
83
- required
84
- ></textarea>
85
- </div>
86
- <div class="action-bar">
87
- <button class="btn btn-primary" onclick="handleTextUpload()">
88
- 📤 submit
89
- </button>
90
- <div class="status-indicator" id="textUploadStatus"></div>
91
- </div>
92
- </div>
93
- </section>
94
-
95
- <section id="label-management" class="card" style="display: none;">
96
- <h3 class="card-title">GRAPH MANAGE(neo4j)</h3>
97
- <div class="action-bar" style="margin-bottom: 1rem;">
98
- <button class="btn btn-secondary" onclick="refreshLabels()">
99
- 🔄 refresh
100
- </button>
101
- </div>
102
- <div id="label-list" class="label-container">
103
- </div>
104
- </section>
105
-
106
- <!-- search -->
107
- <section id="query" class="card" style="display: none;">
108
- <h3 class="card-title">SEARCH API</h3>
109
- <select class="input-field" style="margin-bottom: 1rem;">
110
- <option value="local">local search</option>
111
- <option value="global">global search</option>
112
- <option value="native">native search</option>
113
- <option value="hybrid">hybrid search</option>
114
- <option value="mix">mix search</option>
115
- </select>
116
- <textarea
117
- class="input-field"
118
- placeholder="enter your content..."
119
- style="height: 120px; resize: vertical;"
120
- ></textarea>
121
- <div style="margin-top: 1rem; display: flex; gap: 0.5rem;">
122
- <button class="btn btn-primary">🔍 searching</button>
123
- <label class="btn btn-secondary">
124
- <input type="checkbox" style="margin-right: 0.5rem;">stream modal
125
- </label>
126
- </div>
127
- <div class="results"
128
- style="margin-top: 1rem; padding: 1rem; border: 1px solid var(--border); border-radius: 8px;"></div>
129
- </section>
130
-
131
-
132
- <section id="status" class="card" style="display: none;">
133
- <h3 class="card-title">System Status</h3>
134
- <div class="status-grid">
135
- <div class="status-card health-status">
136
- <div class="status-header">
137
- <i class="status-icon fas fa-heartbeat"></i>
138
- <h4>HEATH STATUS</h4>
139
- </div>
140
- <div class="status-badge" id="healthStatus">checking...</div>
141
- </div>
142
-
143
- <!-- 存储状态 -->
144
- <div class="status-card storage-status">
145
- <div class="status-header">
146
- <i class="status-icon fas fa-database"></i>
147
- <h4>Storage status</h4>
148
- </div>
149
- <div class="progress-container">
150
- <progress value="0" max="100" id="storageProgress"></progress>
151
- <div class="progress-labels">
152
- <span id="indexedFiles">Indexed files:0</span>
153
- <span id="storageUsage">Use ratio:0%</span>
154
- </div>
155
- </div>
156
- </div>
157
-
158
- <div class="status-card model-config">
159
- <div class="status-header">
160
- <i class="status-icon fas fa-brain"></i>
161
- <h4>LLM configuration</h4>
162
- </div>
163
- <dl class="config-list">
164
- <dt>LLM MODEL</dt>
165
- <dd id="llmModel">Loading...</dd>
166
-
167
- <dt>Embedded model</dt>
168
- <dd id="embedModel">Loading...</dd>
169
-
170
- <dt>Max token</dt>
171
- <dd id="maxTokens">0</dd>
172
- </dl>
173
- </div>
174
-
175
- <div class="status-card directory-info">
176
- <div class="status-header">
177
- <i class="status-icon fas fa-folder-open"></i>
178
- <h4>Catalog information</h4>
179
- </div>
180
- <div class="directory-list">
181
- <div class="directory-item">
182
- <span class="directory-label">Work directory:</span>
183
- <span class="directory-path" id="workingDir"></span>
184
- </div>
185
- <div class="directory-item">
186
- <span class="directory-label">Input directory:</span>
187
- <span class="directory-path" id="inputDir"></span>
188
- </div>
189
- </div>
190
- </div>
191
-
192
- <div class="status-card directory-info">
193
- <div class="status-header">
194
- <i class="status-icon fas fa-folder-open"></i>
195
- <h4>Store information</h4>
196
- </div>
197
- <div class="directory-list">
198
- <div class="directory-item">
199
- <span class="directory-label">kv_storage:</span>
200
- <span class="directory-path" id="kv_storage"></span>
201
- </div>
202
- <div class="directory-item">
203
- <span class="directory-label">doc_status_storage:</span>
204
- <span class="directory-path" id="doc_status_storage"></span>
205
- </div>
206
- <div class="directory-item">
207
- <span class="directory-label">graph_storage:</span>
208
- <span class="directory-path" id="graph_storage"></span>
209
- </div>
210
- <div class="directory-item">
211
- <span class="directory-label">vector_storage:</span>
212
- <span class="directory-path" id="vector_storage"></span>
213
- </div>
214
- </div>
215
- </div>
216
-
217
- </div>
218
- </section>
219
- </main>
220
- </div>
221
- <div id="graph-modal" class="modal">
222
- <div class="modal-content">
223
- <div class="modal-header">
224
- <h3 id="graph-title">GRAPH MANAGE</h3>
225
- <button class="btn btn-close" onclick="closeGraphModal()">&times;</button>
226
- </div>
227
- <div class="modal-body">
228
- <div id="graph-container">
229
- <svg id="graph-svg" width="100%" height="600px">
230
- </svg>
231
- </div>
232
- </div>
233
- <div class="modal-footer">
234
- <button class="btn btn-secondary" onclick="closeGraphModal()">SHUT DOWN</button>
235
- </div>
236
- <div class="resize-handle"></div>
237
-
238
- </div>
239
- </div>
240
- <script>
241
- const dropzone = document.getElementById('dropzone');
242
-
243
- dropzone.addEventListener('dragover', (e) => {
244
- e.preventDefault();
245
- dropzone.classList.add('active');
246
- });
247
-
248
- dropzone.addEventListener('dragleave', () => {
249
- dropzone.classList.remove('active');
250
- });
251
-
252
- dropzone.addEventListener('drop', (e) => {
253
- e.preventDefault();
254
- dropzone.classList.remove('active');
255
- const files = e.dataTransfer.files;
256
- handleFiles(files);
257
- });
258
-
259
- function handleFiles(files) {
260
- console.log('selected file:', files);
261
- }
262
-
263
- function showSection(sectionId) {
264
- // Hide all content blocks
265
- const sections = document.querySelectorAll('.main-content .card');
266
- sections.forEach(section => {
267
- section.style.display = 'none';
268
- });
269
-
270
- // Display target block
271
- const targetSection = document.getElementById(sectionId);
272
- if (targetSection) {
273
- targetSection.style.display = 'block';
274
- }
275
-
276
- // Update button activation status (optional)
277
- const buttons = document.querySelectorAll('.nav-menu button');
278
- buttons.forEach(button => {
279
- button.classList.remove('active');
280
- });
281
- event.target.classList.add('active');
282
- }
283
-
284
- // Initialize the display document management module
285
- showSection('documents');
286
- </script>
287
- <script src="./js/lightrag.js"></script>
288
- <script src="./js/graph.js"></script>
289
- <script src="https://d3js.org/d3.v7.min.js"></script>
290
- </body>
291
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lightrag/api/webui_depricated/static/js/__init__.py DELETED
File without changes
lightrag/api/webui_depricated/static/js/lightrag.js DELETED
@@ -1,500 +0,0 @@
1
- // lightrag.js
2
- // init
3
- function initializeApp() {
4
- setupFileUpload();
5
- setupQueryHandler();
6
- setupSectionObserver();
7
- updateFileList();
8
- // textarea count
9
- const textArea = document.getElementById('textContent');
10
- if (textArea) {
11
- const charCount = document.createElement('div');
12
- charCount.className = 'char-count';
13
- textArea.parentNode.appendChild(charCount);
14
-
15
- textArea.addEventListener('input', () => {
16
- const count = textArea.value.length;
17
- charCount.textContent = `input ${count} character`;
18
- charCount.style.color = count > 10000 ? '#ef4444' : 'var (--text-secondary)'
19
- });
20
- }
21
- }
22
-
23
- // api request
24
- async function apiRequest(endpoint, method = 'GET', body = null) {
25
- const options = {
26
- method,
27
- headers: {
28
- 'Content-Type': 'application/json'
29
- }
30
- };
31
-
32
- if (body) {
33
- options.body = JSON.stringify(body);
34
- }
35
-
36
- try {
37
- const response = await fetch(`${endpoint}`, options);
38
- if (!response.ok) {
39
- throw new Error(`request failed: ${response.status}`);
40
- }
41
- return response.json();
42
- } catch (error) {
43
- console.error('API REQUEST ERROR:', error);
44
- showToast(error.message, 'error');
45
- throw error;
46
- }
47
- }
48
-
49
- async function handleTextUpload() {
50
- const description = document.getElementById('textDescription').value;
51
- const content = document.getElementById('textContent').value.trim();
52
- const statusDiv = document.getElementById('textUploadStatus');
53
-
54
- // clear status tip
55
- statusDiv.className = 'status-indicator';
56
- statusDiv.textContent = '';
57
-
58
- // input valid
59
- if (!content) {
60
- showStatus('error', 'TEXT CONTENT NOT NULL', statusDiv);
61
- return;
62
- }
63
-
64
- try {
65
- showStatus('loading', 'UPLOADING...', statusDiv);
66
-
67
- const payload = {
68
- text: content,
69
- ...(description && {description})
70
- };
71
-
72
- const response = await fetch(`/documents/text`, {
73
- method: 'POST',
74
- headers: {
75
- 'Content-Type': 'application/json'
76
- },
77
- body: JSON.stringify(payload)
78
- });
79
-
80
- if (!response.ok) {
81
- const errorData = await response.json();
82
- throw new Error(errorData.detail || 'UPLOAD FAILED');
83
- }
84
-
85
- const result = await response.json();
86
-
87
- showStatus('success', `✅ ${result.message} (documents: ${result.document_count})`, statusDiv);
88
-
89
-
90
- document.getElementById('textContent').value = '';
91
-
92
- // update file list
93
- updateFileList();
94
-
95
- } catch (error) {
96
- showStatus('error', `❌ ERROR: ${error.message}`, statusDiv);
97
- console.error('FILE UPLOAD FAILED:', error);
98
- }
99
- }
100
-
101
- function showStatus(type, message, container) {
102
- container.textContent = message;
103
- container.className = `status-indicator ${type}`;
104
-
105
- //auto clear success status
106
- if (type === 'success') {
107
- setTimeout(() => {
108
- container.textContent = '';
109
- container.className = 'status-indicator';
110
- }, 5000);
111
- }
112
- }
113
-
114
- // upload file
115
- function setupFileUpload() {
116
- const dropzone = document.getElementById('dropzone');
117
- const fileInput = document.getElementById('fileInput');
118
-
119
-
120
- // Drag and drop event handling
121
- dropzone.addEventListener('dragover', (e) => {
122
- e.preventDefault();
123
- dropzone.classList.add('active');
124
- });
125
-
126
- dropzone.addEventListener('dragleave', () => {
127
- dropzone.classList.remove('active');
128
- });
129
-
130
- dropzone.addEventListener('drop', async (e) => {
131
- e.preventDefault();
132
- dropzone.classList.remove('active');
133
- await handleFiles(e.dataTransfer.files);
134
- });
135
-
136
-
137
- fileInput.addEventListener('change', async (e) => {
138
- await handleFiles(e.target.files);
139
- });
140
- }
141
-
142
- async function handleFiles(files) {
143
- const formData = new FormData();
144
- for (const file of files) {
145
- formData.append('file', file);
146
- }
147
- const statusDiv = document.getElementById('fileUploadStatus');
148
-
149
-
150
- statusDiv.className = 'status-indicator';
151
- statusDiv.textContent = '';
152
- try {
153
- showStatus('loading', 'UPLOADING...', statusDiv);
154
- const response = await fetch(`/documents/upload`, {
155
- method: 'POST',
156
- body: formData
157
- });
158
- const result = await response.json();
159
- showStatus('success', `✅ ${result.message} `, statusDiv);
160
- updateFileList();
161
- } catch (error) {
162
- showToast(error.message, 'error');
163
- }
164
- }
165
-
166
-
167
- async function updateFileList() {
168
- const fileList = document.querySelector('.file-list');
169
- try {
170
- const status = await apiRequest('/health');
171
- fileList.innerHTML = `
172
- <div>INDEXED FILE: ${status.indexed_files_count}</div>
173
- `;
174
- } catch (error) {
175
- fileList.innerHTML = 'UNABLE TO OBTAIN FILE LIST';
176
- }
177
- }
178
-
179
- // Intelligent retrieval processing
180
- function setupQueryHandler() {
181
- document.querySelector('#query .btn-primary').addEventListener('click', handleQuery);
182
- }
183
-
184
- async function handleQuery() {
185
- const queryInput = document.querySelector('#query textarea');
186
- const modeSelect = document.querySelector('#query select');
187
- const streamCheckbox = document.querySelector('#query input[type="checkbox"]');
188
- const resultsDiv = document.querySelector('#query .results');
189
-
190
- const payload = {
191
- query: queryInput.value,
192
- mode: modeSelect.value,
193
- stream: streamCheckbox.checked
194
- };
195
-
196
- resultsDiv.innerHTML = '<div class="loading">SEARCHING...</div>';
197
-
198
- try {
199
- if (payload.stream) {
200
- await handleStreamingQuery(payload, resultsDiv);
201
- } else {
202
- const result = await apiRequest('/query', 'POST', payload);
203
- resultsDiv.innerHTML = `<div class="result">${result.response}</div>`;
204
- }
205
- } catch (error) {
206
- resultsDiv.innerHTML = `<div class="error">SEARCH FAILED: ${error.message}</div>`;
207
- }
208
- }
209
-
210
- // handle stream api
211
- async function handleStreamingQuery(payload, resultsDiv) {
212
- try {
213
- const response = await fetch(`/query/stream`, {
214
- method: 'POST',
215
- headers: {'Content-Type': 'application/json'},
216
- body: JSON.stringify(payload)
217
- });
218
-
219
-
220
- const contentType = response.headers.get('Content-Type') || '';
221
- const validTypes = ['application/x-ndjson', 'application/json'];
222
- if (!validTypes.some(t => contentType.includes(t))) {
223
- throw new Error(`INVALID CONTENT TYPE: ${contentType}`);
224
- }
225
-
226
- const reader = response.body.getReader();
227
- const decoder = new TextDecoder('utf-8');
228
- let buffer = '';
229
-
230
- resultsDiv.innerHTML = '';
231
-
232
- while (true) {
233
- const {done, value} = await reader.read();
234
- if (done) break;
235
-
236
- buffer += decoder.decode(value, {stream: true});
237
-
238
- // Split by line break (NDJSON format requirement)
239
- let lineEndIndex;
240
- while ((lineEndIndex = buffer.indexOf('\n')) >= 0) {
241
- const line = buffer.slice(0, lineEndIndex).trim();
242
- buffer = buffer.slice(lineEndIndex + 1);
243
-
244
- if (!line) continue;
245
-
246
- try {
247
- const data = JSON.parse(line);
248
-
249
- if (data.response) {
250
- resultsDiv.innerHTML += data.response;
251
- resultsDiv.scrollTop = resultsDiv.scrollHeight;
252
- }
253
-
254
- if (data.error) {
255
- resultsDiv.innerHTML += `<div class="error">${data.error}</div>`;
256
- }
257
- } catch (error) {
258
- console.error('JSON PARSING FAILED:', {
259
- error,
260
- rawLine: line,
261
- bufferRemaining: buffer
262
- });
263
- }
264
- }
265
- }
266
-
267
- // Process remaining data
268
- if (buffer.trim()) {
269
- try {
270
- const data = JSON.parse(buffer.trim());
271
- if (data.response) {
272
- resultsDiv.innerHTML += data.response;
273
- }
274
- } catch (error) {
275
- console.error('TAIL DATA PARSING FAILED:', error);
276
- }
277
- }
278
-
279
- } catch (error) {
280
- resultsDiv.innerHTML = `<div class="error">REQUEST FAILED: ${error.message}</div>`;
281
- }
282
- }
283
-
284
-
285
- // Knowledge Q&A Processing
286
- function setupChatHandler() {
287
- const sendButton = document.querySelector('#chat button');
288
- const chatInput = document.querySelector('#chat input');
289
-
290
- sendButton.addEventListener('click', () => handleChat(chatInput));
291
- chatInput.addEventListener('keypress', (e) => {
292
- if (e.key === 'Enter') handleChat(chatInput);
293
- });
294
- }
295
-
296
- async function handleChat(chatInput) {
297
- const chatHistory = document.querySelector('#chat .chat-history');
298
-
299
-
300
- const userMessage = document.createElement('div');
301
- userMessage.className = 'message user';
302
- userMessage.textContent = chatInput.value;
303
- chatHistory.appendChild(userMessage);
304
-
305
-
306
- const botMessage = document.createElement('div');
307
- botMessage.className = 'message bot loading';
308
- botMessage.textContent = 'THINKING...';
309
- chatHistory.appendChild(botMessage);
310
- chatHistory.scrollTop = chatHistory.scrollHeight;
311
-
312
- try {
313
- const response = await fetch(`/api/chat`, {
314
- method: 'POST',
315
- headers: {'Content-Type': 'application/json'},
316
- body: JSON.stringify({
317
- messages: [{role: "user", content: chatInput.value}],
318
- stream: true
319
- })
320
- });
321
-
322
- const reader = response.body.getReader();
323
- const decoder = new TextDecoder();
324
- botMessage.classList.remove('loading');
325
- botMessage.textContent = '';
326
-
327
- while (true) {
328
- const {done, value} = await reader.read();
329
- if (done) break;
330
-
331
- const chunk = decoder.decode(value);
332
- const data = JSON.parse(chunk);
333
- botMessage.textContent += data.message?.content || '';
334
- chatHistory.scrollTop = chatHistory.scrollHeight;
335
- }
336
- } catch (error) {
337
- botMessage.textContent = `ERROR: ${error.message}`;
338
- botMessage.classList.add('error');
339
- }
340
-
341
- chatInput.value = '';
342
- }
343
-
344
- // system status update
345
- async function updateSystemStatus() {
346
- const statusElements = {
347
- health: document.getElementById('healthStatus'),
348
- storageProgress: document.getElementById('storageProgress'),
349
- indexedFiles: document.getElementById('indexedFiles'),
350
- storageUsage: document.getElementById('storageUsage'),
351
- llmModel: document.getElementById('llmModel'),
352
- embedModel: document.getElementById('embedModel'),
353
- maxTokens: document.getElementById('maxTokens'),
354
- workingDir: document.getElementById('workingDir'),
355
- inputDir: document.getElementById('inputDir'),
356
- kv_storage: document.getElementById("kv_storage"),
357
- doc_status_storage: document.getElementById("doc_status_storage"),
358
- graph_storage: document.getElementById("graph_storage"),
359
- vector_storage: document.getElementById("vector_storage")
360
- };
361
-
362
- try {
363
- const status = await apiRequest('/health');
364
-
365
- // heath status
366
- statusElements.health.className = 'status-badge';
367
- statusElements.health.textContent = status.status === 'healthy' ?
368
- '✅ Healthy operation in progress' : '⚠️ Service exception';
369
-
370
- // kv status
371
- const progressValue = Math.min(Math.round((status.indexed_files_count / 1000) * 100), 100);
372
- statusElements.storageProgress.value = progressValue;
373
- statusElements.indexedFiles.textContent = `INDEXED FILES:${status.indexed_files_count}`;
374
- statusElements.storageUsage.textContent = `USE PERCENT:${progressValue}%`;
375
-
376
- // model state
377
- statusElements.llmModel.textContent = `${status.configuration.llm_model} (${status.configuration.llm_binding})`;
378
- statusElements.embedModel.textContent = `${status.configuration.embedding_model} (${status.configuration.embedding_binding})`;
379
- statusElements.maxTokens.textContent = status.configuration.max_tokens.toLocaleString();
380
-
381
- // dir msg
382
- statusElements.workingDir.textContent = status.working_directory;
383
- statusElements.inputDir.textContent = status.input_directory;
384
-
385
- // stack msg
386
- statusElements.kv_storage.textContent = status.configuration.kv_storage;
387
- statusElements.doc_status_storage.textContent = status.configuration.doc_status_storage;
388
- statusElements.graph_storage.textContent = status.configuration.graph_storage;
389
- statusElements.vector_storage.textContent = status.configuration.vector_storage
390
-
391
- } catch (error) {
392
- statusElements.health.className = 'status-badge error';
393
- statusElements.health.textContent = '❌GET STATUS FAILED';
394
- statusElements.storageProgress.value = 0;
395
- statusElements.indexedFiles.textContent = 'INDEXED FILES:GET FAILED';
396
- console.error('STATUS UPDATE FAILED:', error);
397
- }
398
- }
399
-
400
-
401
- // Area switching monitoring
402
- function setupSectionObserver() {
403
- const observer = new MutationObserver(mutations => {
404
- mutations.forEach(mutation => {
405
- if (mutation.attributeName === 'style') {
406
- const isVisible = mutation.target.style.display !== 'none';
407
- if (isVisible && mutation.target.id === 'status') {
408
- updateSystemStatus();
409
- }
410
- }
411
- });
412
- });
413
-
414
- document.querySelectorAll('.card').forEach(section => {
415
- observer.observe(section, {attributes: true});
416
- });
417
- }
418
-
419
- // Display prompt information
420
- function showToast(message, type = 'info') {
421
- const toast = document.createElement('div');
422
- toast.className = `toast ${type}`;
423
- toast.textContent = message;
424
- document.body.appendChild(toast);
425
-
426
- setTimeout(() => {
427
- toast.remove();
428
- }, 3000);
429
- }
430
-
431
-
432
- // Dynamically load tag list
433
- async function loadLabels() {
434
- try {
435
- const response = await fetch('/graph/label/list');
436
- const labels = await response.json();
437
- renderLabels(labels);
438
- } catch (error) {
439
- console.error('DYNAMICALLY LOAD TAG LIST FAILED:', error);
440
- }
441
- }
442
-
443
- async function loadGraph(label) {
444
- try {
445
- // render label list
446
- openGraphModal(label)
447
- } catch (error) {
448
- console.error('LOADING LABEL FAILED:', error);
449
-
450
-
451
- const labelList = document.getElementById("label-list");
452
- labelList.innerHTML = `
453
- <div class="error-message">
454
- LOADING ERROR: ${error.message}
455
- </div>
456
- `;
457
- }
458
- }
459
-
460
- // render graph label list
461
- function renderLabels(labels) {
462
- const container = document.getElementById('label-list');
463
- container.innerHTML = labels.map(label => `
464
- <div class="label-item">
465
- <span style="font-weight: 500; color: var(--text-primary);">
466
- ${label}
467
- </span>
468
- <div class="label-actions">
469
- <button class="btn btn-primary"
470
- onclick="handleLabelAction('${label}')">
471
- 📋 graph
472
- </button>
473
- </div>
474
- </div>
475
- `).join('');
476
- }
477
-
478
-
479
- function handleLabelAction(label) {
480
- loadGraph(label)
481
- }
482
-
483
-
484
- function refreshLabels() {
485
- showToast('LOADING GRAPH LABELS...', 'info');
486
- loadLabels();
487
- }
488
-
489
- function showToast(message, type = 'info') {
490
- const toast = document.createElement('div');
491
- toast.className = `toast toast-${type}`;
492
- toast.textContent = message;
493
- document.body.appendChild(toast);
494
-
495
- setTimeout(() => {
496
- toast.remove();
497
- }, 3000);
498
- }
499
-
500
- document.addEventListener('DOMContentLoaded', initializeApp);