lemonade-sdk 8.1.9__py3-none-any.whl → 8.1.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lemonade-sdk might be problematic. Click here for more details.
- lemonade/common/inference_engines.py +13 -4
- lemonade/common/system_info.py +570 -1
- lemonade/tools/flm/__init__.py +1 -0
- lemonade/tools/flm/utils.py +255 -0
- lemonade/tools/llamacpp/utils.py +62 -13
- lemonade/tools/server/flm.py +137 -0
- lemonade/tools/server/llamacpp.py +23 -5
- lemonade/tools/server/serve.py +292 -135
- lemonade/tools/server/static/js/chat.js +165 -82
- lemonade/tools/server/static/js/models.js +87 -54
- lemonade/tools/server/static/js/shared.js +5 -3
- lemonade/tools/server/static/logs.html +47 -0
- lemonade/tools/server/static/styles.css +159 -8
- lemonade/tools/server/static/webapp.html +28 -10
- lemonade/tools/server/tray.py +158 -38
- lemonade/tools/server/utils/macos_tray.py +226 -0
- lemonade/tools/server/utils/{system_tray.py → windows_tray.py} +13 -0
- lemonade/tools/server/webapp.py +4 -1
- lemonade/tools/server/wrapped_server.py +91 -25
- lemonade/version.py +1 -1
- lemonade_install/install.py +25 -2
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/METADATA +9 -6
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/RECORD +33 -28
- lemonade_server/cli.py +105 -14
- lemonade_server/model_manager.py +186 -45
- lemonade_server/pydantic_models.py +25 -1
- lemonade_server/server_models.json +162 -62
- lemonade_server/settings.py +39 -39
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/WHEEL +0 -0
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/entry_points.txt +0 -0
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/licenses/LICENSE +0 -0
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/licenses/NOTICE.md +0 -0
- {lemonade_sdk-8.1.9.dist-info → lemonade_sdk-8.1.11.dist-info}/top_level.txt +0 -0
|
@@ -181,7 +181,7 @@ async function loadModelStandardized(modelId, options = {}) {
|
|
|
181
181
|
// Update load button if provided
|
|
182
182
|
if (loadButton) {
|
|
183
183
|
loadButton.disabled = true;
|
|
184
|
-
loadButton.textContent = '
|
|
184
|
+
loadButton.textContent = '⏳';
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
// Update status indicator to show loading state
|
|
@@ -246,7 +246,8 @@ async function loadModelStandardized(modelId, options = {}) {
|
|
|
246
246
|
// Reset load button if provided
|
|
247
247
|
if (loadButton) {
|
|
248
248
|
loadButton.disabled = false;
|
|
249
|
-
loadButton.textContent = '
|
|
249
|
+
loadButton.textContent = '🚀';
|
|
250
|
+
loadButton.classList.remove('loading');
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
// Reset chat controls
|
|
@@ -280,7 +281,8 @@ async function loadModelStandardized(modelId, options = {}) {
|
|
|
280
281
|
// Reset load button if provided
|
|
281
282
|
if (loadButton) {
|
|
282
283
|
loadButton.disabled = false;
|
|
283
|
-
loadButton.textContent = '
|
|
284
|
+
loadButton.textContent = '🚀';
|
|
285
|
+
loadButton.classList.remove('loading');
|
|
284
286
|
}
|
|
285
287
|
|
|
286
288
|
// Reset status indicator on error
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Lemonade Server Logs</title>
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
font-family: monospace;
|
|
9
|
+
background: #1e1e1e;
|
|
10
|
+
color: #d4d4d4;
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
}
|
|
14
|
+
#log-container {
|
|
15
|
+
padding: 10px;
|
|
16
|
+
height: 100vh;
|
|
17
|
+
overflow-y: auto;
|
|
18
|
+
white-space: pre-wrap;
|
|
19
|
+
}
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div id="log-container"></div>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
function stripAnsi(str) {
|
|
27
|
+
return str.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '');
|
|
28
|
+
}
|
|
29
|
+
const logContainer = document.getElementById("log-container");
|
|
30
|
+
const ws = new WebSocket(`ws://${location.host}/api/v1/logs/ws`);
|
|
31
|
+
|
|
32
|
+
ws.onmessage = (event) => {
|
|
33
|
+
const line = document.createElement("div");
|
|
34
|
+
line.textContent = stripAnsi(event.data);
|
|
35
|
+
logContainer.appendChild(line);
|
|
36
|
+
logContainer.scrollTop = logContainer.scrollHeight; // auto scroll
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
ws.onclose = () => {
|
|
40
|
+
const msg = document.createElement("div");
|
|
41
|
+
msg.textContent = "[Disconnected from log stream]";
|
|
42
|
+
msg.style.color = "red";
|
|
43
|
+
logContainer.appendChild(msg);
|
|
44
|
+
};
|
|
45
|
+
</script>
|
|
46
|
+
</body>
|
|
47
|
+
</html>
|
|
@@ -99,6 +99,15 @@ body::before {
|
|
|
99
99
|
.brand-title a {
|
|
100
100
|
color: inherit;
|
|
101
101
|
text-decoration: none;
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 0.5rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.brand-icon {
|
|
108
|
+
width: 1.5rem;
|
|
109
|
+
height: 1.5rem;
|
|
110
|
+
vertical-align: middle;
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
.navbar-links {
|
|
@@ -167,6 +176,9 @@ body::before {
|
|
|
167
176
|
width: 100%;
|
|
168
177
|
margin-left: 1rem;
|
|
169
178
|
margin-right: 1rem;
|
|
179
|
+
/* Removing only the bottom border and shadow for the content tab gap to look nicer */
|
|
180
|
+
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0);
|
|
181
|
+
border-bottom: none;
|
|
170
182
|
}
|
|
171
183
|
|
|
172
184
|
.tabs {
|
|
@@ -213,14 +225,24 @@ body::before {
|
|
|
213
225
|
position: relative;
|
|
214
226
|
}
|
|
215
227
|
|
|
228
|
+
/* Wrapper for the select element with embedded status light */
|
|
229
|
+
.model-select-wrapper {
|
|
230
|
+
position: relative;
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
}
|
|
234
|
+
|
|
216
235
|
.status-light {
|
|
217
236
|
width: 8px;
|
|
218
237
|
height: 8px;
|
|
219
238
|
border-radius: 50%;
|
|
220
|
-
position:
|
|
239
|
+
position: absolute;
|
|
240
|
+
left: 8px;
|
|
241
|
+
top: 50%;
|
|
242
|
+
transform: translateY(-50%);
|
|
221
243
|
transition: all var(--transition-fast);
|
|
222
244
|
flex-shrink: 0;
|
|
223
|
-
|
|
245
|
+
z-index: 10;
|
|
224
246
|
}
|
|
225
247
|
|
|
226
248
|
.status-light::before {
|
|
@@ -288,7 +310,7 @@ body::before {
|
|
|
288
310
|
|
|
289
311
|
/* Base styles for the select element */
|
|
290
312
|
.model-select {
|
|
291
|
-
padding: 0.5rem 0.75rem;
|
|
313
|
+
padding: 0.5rem 0.75rem 0.5rem 1.5rem;
|
|
292
314
|
border: 1px solid #ddd;
|
|
293
315
|
border-radius: 6px;
|
|
294
316
|
background: #fafafa;
|
|
@@ -391,11 +413,18 @@ button:disabled {
|
|
|
391
413
|
display: flex;
|
|
392
414
|
}
|
|
393
415
|
|
|
416
|
+
.tab-content-wrapper {
|
|
417
|
+
width: 85%;
|
|
418
|
+
}
|
|
419
|
+
|
|
394
420
|
.tab-content {
|
|
395
421
|
display: none;
|
|
396
422
|
padding: 2em;
|
|
397
423
|
background: #fafafa;
|
|
398
424
|
border-radius: 0 0 8px 8px;
|
|
425
|
+
/* adding border and shadow that was removed for the gap look from higher div */
|
|
426
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
427
|
+
border: 1px solid #e0e0e0;
|
|
399
428
|
}
|
|
400
429
|
|
|
401
430
|
.tab-content.active {
|
|
@@ -406,7 +435,9 @@ button:disabled {
|
|
|
406
435
|
.chat-container {
|
|
407
436
|
display: flex;
|
|
408
437
|
flex-direction: column;
|
|
409
|
-
|
|
438
|
+
/* Max space available in viewport
|
|
439
|
+
This also prevents the chat-history section to resize lower than a certain point */
|
|
440
|
+
min-height: calc(100vh - 550px);
|
|
410
441
|
min-width: 300px;
|
|
411
442
|
max-width: 100%;
|
|
412
443
|
width: 100%;
|
|
@@ -414,18 +445,37 @@ button:disabled {
|
|
|
414
445
|
border: 1px solid #e0e0e0;
|
|
415
446
|
border-radius: 8px;
|
|
416
447
|
background: #fff;
|
|
417
|
-
|
|
418
|
-
|
|
448
|
+
/* Use a semi-fixed chat 'window' height so streaming content never expands the page.
|
|
449
|
+
The chat-history area inside will scroll. The CSS variable allows easy tuning. */
|
|
450
|
+
--chat-height: 520px;
|
|
451
|
+
/* Allow vertical resizing by the user while keeping horizontal size fixed.
|
|
452
|
+
Constrain the resize with min/max heights so it stays usable and doesn't overflow the viewport. */
|
|
453
|
+
resize: vertical;
|
|
454
|
+
height: var(--chat-height);
|
|
455
|
+
max-height: calc(100vh - 120px);
|
|
456
|
+
overflow: hidden; /* hide overflow at container level; chat-history will scroll */
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Responsive fallback: if the viewport height is small, cap the chat window to fit */
|
|
460
|
+
@media (max-height: 700px) {
|
|
461
|
+
.chat-container {
|
|
462
|
+
height: calc(100vh - 180px); /* leave space for navbar/footer */
|
|
463
|
+
}
|
|
419
464
|
}
|
|
420
465
|
|
|
421
466
|
.chat-history {
|
|
422
|
-
|
|
467
|
+
/* Make chat history take remaining space in the chat container and scroll when content
|
|
468
|
+
exceeds this space. This prevents streaming text from expanding the overall layout. */
|
|
469
|
+
flex: 1 1 auto;
|
|
423
470
|
overflow-y: auto;
|
|
471
|
+
-webkit-overflow-scrolling: touch;
|
|
424
472
|
padding: 1em;
|
|
425
473
|
border-bottom: 1px solid #e0e0e0;
|
|
426
474
|
display: flex;
|
|
427
475
|
flex-direction: column;
|
|
428
476
|
gap: 0.5em;
|
|
477
|
+
/* Optional visual hint for scrollable content */
|
|
478
|
+
scrollbar-width: thin;
|
|
429
479
|
}
|
|
430
480
|
|
|
431
481
|
.chat-message {
|
|
@@ -1492,6 +1542,11 @@ button:disabled {
|
|
|
1492
1542
|
font-size: 1.3rem;
|
|
1493
1543
|
}
|
|
1494
1544
|
|
|
1545
|
+
.brand-icon {
|
|
1546
|
+
width: 1.3rem;
|
|
1547
|
+
height: 1.3rem;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1495
1550
|
.navbar-links {
|
|
1496
1551
|
gap: 1.5rem;
|
|
1497
1552
|
font-size: 1rem;
|
|
@@ -1507,6 +1562,11 @@ button:disabled {
|
|
|
1507
1562
|
font-size: 1.2rem;
|
|
1508
1563
|
}
|
|
1509
1564
|
|
|
1565
|
+
.brand-icon {
|
|
1566
|
+
width: 1.2rem;
|
|
1567
|
+
height: 1.2rem;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1510
1570
|
.navbar-links {
|
|
1511
1571
|
gap: 1rem;
|
|
1512
1572
|
font-size: 0.9rem;
|
|
@@ -1838,6 +1898,53 @@ button:disabled {
|
|
|
1838
1898
|
align-items: center;
|
|
1839
1899
|
}
|
|
1840
1900
|
|
|
1901
|
+
/* FastFlowLM notice styles */
|
|
1902
|
+
.flm-notice {
|
|
1903
|
+
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
|
|
1904
|
+
border: 1px solid #ffeaa7;
|
|
1905
|
+
border-left: 4px solid #f39c12;
|
|
1906
|
+
border-radius: 8px;
|
|
1907
|
+
margin-bottom: 1.5rem;
|
|
1908
|
+
box-shadow: 0 2px 8px rgba(243, 156, 18, 0.1);
|
|
1909
|
+
animation: fadeIn 0.3s ease;
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
.flm-notice-content {
|
|
1913
|
+
display: flex;
|
|
1914
|
+
align-items: flex-start;
|
|
1915
|
+
gap: 0.75rem;
|
|
1916
|
+
padding: 1rem 1.25rem;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
.flm-notice-icon {
|
|
1920
|
+
font-size: 1.2rem;
|
|
1921
|
+
flex-shrink: 0;
|
|
1922
|
+
margin-top: 0.1rem;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
.flm-notice-text {
|
|
1926
|
+
flex: 1;
|
|
1927
|
+
font-size: 0.95rem;
|
|
1928
|
+
line-height: 1.5;
|
|
1929
|
+
color: #856404;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
.flm-notice-text strong {
|
|
1933
|
+
color: #6c5ce7;
|
|
1934
|
+
font-weight: 600;
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
.flm-notice-text a {
|
|
1938
|
+
color: var(--info-primary);
|
|
1939
|
+
text-decoration: none;
|
|
1940
|
+
font-weight: 500;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
.flm-notice-text a:hover {
|
|
1944
|
+
text-decoration: underline;
|
|
1945
|
+
color: var(--info-hover);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1841
1948
|
.error-banner .close-btn {
|
|
1842
1949
|
background: none;
|
|
1843
1950
|
border: none;
|
|
@@ -2275,4 +2382,48 @@ button:disabled {
|
|
|
2275
2382
|
0 8px 25px rgba(200, 88, 108, 0.2),
|
|
2276
2383
|
0 3px 10px rgba(0, 0, 0, 0.1),
|
|
2277
2384
|
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
|
2278
|
-
}
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
|
|
2388
|
+
/* Dropdown styling */
|
|
2389
|
+
.dropdown {
|
|
2390
|
+
position: relative;
|
|
2391
|
+
display: inline-block;
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
.dropbtn {
|
|
2395
|
+
background-color: transparent;
|
|
2396
|
+
border: none;
|
|
2397
|
+
font-size: 16px;
|
|
2398
|
+
cursor: pointer;
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
.dropdown-content {
|
|
2402
|
+
display: none;
|
|
2403
|
+
position: absolute;
|
|
2404
|
+
right: 0; /* align to the right edge of the parent */
|
|
2405
|
+
left: auto; /* prevent left alignment */
|
|
2406
|
+
top: calc(100% + 1px); /* opens 8px below the button */
|
|
2407
|
+
background-color: #ffe76c;
|
|
2408
|
+
border-radius: 8px;
|
|
2409
|
+
min-width: 140px;
|
|
2410
|
+
box-shadow: 0px 8px 16px rgba(0,0,0,0.2);
|
|
2411
|
+
z-index: 1000;
|
|
2412
|
+
overflow: hidden;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
.dropdown-content a {
|
|
2416
|
+
color: black;
|
|
2417
|
+
font-size: 12px; /* smaller font */
|
|
2418
|
+
padding: 8px 12px;
|
|
2419
|
+
text-decoration: none;
|
|
2420
|
+
display: block;
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
.dropdown-content a:hover {
|
|
2424
|
+
background-color: #f6c146;
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
.dropdown:hover .dropdown-content {
|
|
2428
|
+
display: block;
|
|
2429
|
+
}
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
window.SERVER_PORT = {{SERVER_PORT}};
|
|
11
11
|
</script>
|
|
12
12
|
{{SERVER_MODELS_JS}}
|
|
13
|
+
{{PLATFORM_JS}}
|
|
13
14
|
</head>
|
|
14
15
|
<body>
|
|
15
16
|
<nav class="navbar" id="navbar">
|
|
16
17
|
<div class="navbar-brand">
|
|
17
|
-
<span class="brand-title"><a href="https://lemonade-server.ai"
|
|
18
|
-
</div>
|
|
18
|
+
<span class="brand-title"><a href="https://lemonade-server.ai"><img src="/static/favicon.ico" alt="🍋" class="brand-icon"> Lemonade Server</a></span>
|
|
19
|
+
</div>
|
|
19
20
|
<div class="navbar-links">
|
|
20
21
|
<a href="https://github.com/lemonade-sdk/lemonade" target="_blank">GitHub</a>
|
|
21
22
|
<a href="https://lemonade-server.ai/docs/" target="_blank">Docs</a>
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
<button class="close-btn" onclick="hideErrorBanner()">×</button>
|
|
30
31
|
</div>
|
|
31
32
|
<main class="main">
|
|
33
|
+
<div class="tab-content-wrapper">
|
|
32
34
|
<div class="tab-container">
|
|
33
35
|
<div class="tabs">
|
|
34
36
|
<div class="tab-group">
|
|
@@ -38,23 +40,32 @@
|
|
|
38
40
|
</div>
|
|
39
41
|
|
|
40
42
|
<div class="model-status-indicator" id="model-status-indicator">
|
|
41
|
-
<div class="
|
|
42
|
-
|
|
43
|
-
<
|
|
44
|
-
|
|
43
|
+
<div class="model-select-wrapper">
|
|
44
|
+
<div class="status-light" id="status-light"></div>
|
|
45
|
+
<select id="model-select" class="model-select">
|
|
46
|
+
<option value="">Pick a model</option>
|
|
47
|
+
</select>
|
|
48
|
+
</div>
|
|
45
49
|
<button class="model-action-btn" id="model-unload-btn" title="Unload model" style="display: flex;">⏏</button>
|
|
50
|
+
<!-- Dropdown -->
|
|
51
|
+
<div class="dropdown">
|
|
52
|
+
<button class="dropbtn" aria-label="Dropdown" style="display: flex;">🛠️</button>
|
|
53
|
+
<div class="dropdown-content">
|
|
54
|
+
<a href="/static/logs.html" target="_blank">View Logs</a>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
46
57
|
</div>
|
|
47
|
-
</div>
|
|
58
|
+
</div>
|
|
48
59
|
<div class="tab-content active" id="content-chat">
|
|
49
60
|
<div class="chat-container">
|
|
50
|
-
<div class="chat-history" id="chat-history"></div>
|
|
61
|
+
<div class="chat-history" id="chat-history" style="overflow-y: auto;"></div>
|
|
51
62
|
<div class="chat-input-row">
|
|
52
63
|
<div class="input-with-indicator">
|
|
53
64
|
<textarea id="chat-input" placeholder="Type your message..." rows="1"></textarea>
|
|
54
65
|
</div>
|
|
55
66
|
<input type="file" id="file-attachment" style="display: none;" multiple accept="image/*">
|
|
56
67
|
<button id="attachment-btn" title="Attach files">📎</button>
|
|
57
|
-
<button id="
|
|
68
|
+
<button id="toggle-btn" title="Start">Start</button>
|
|
58
69
|
</div>
|
|
59
70
|
<div class="attachments-preview-container" id="attachments-preview-container">
|
|
60
71
|
<div class="attachments-preview-row" id="attachments-preview-row"></div>
|
|
@@ -150,6 +161,7 @@
|
|
|
150
161
|
<div class="subcategory" data-recipe="oga-hybrid" onclick="selectRecipe('oga-hybrid')">OGA Hybrid</div>
|
|
151
162
|
<div class="subcategory" data-recipe="oga-npu" onclick="selectRecipe('oga-npu')">OGA NPU</div>
|
|
152
163
|
<div class="subcategory" data-recipe="oga-cpu" onclick="selectRecipe('oga-cpu')">OGA CPU</div>
|
|
164
|
+
<div class="subcategory" data-recipe="flm" onclick="selectRecipe('flm')">FastFlowLM NPU</div>
|
|
153
165
|
</div>
|
|
154
166
|
</div>
|
|
155
167
|
<div class="model-category-section">
|
|
@@ -204,6 +216,7 @@
|
|
|
204
216
|
</label>
|
|
205
217
|
<select id="register-recipe" name="recipe" required>
|
|
206
218
|
<option value="llamacpp">llamacpp</option>
|
|
219
|
+
<option value="flm">flm</option>
|
|
207
220
|
<option value="oga-npu">oga-npu</option>
|
|
208
221
|
<option value="oga-hybrid">oga-hybrid</option>
|
|
209
222
|
<option value="oga-cpu">oga-cpu</option>
|
|
@@ -221,6 +234,11 @@
|
|
|
221
234
|
Reasoning
|
|
222
235
|
<span class="tooltip-icon" data-tooltip="Enable to inform Lemonade Server that the model has reasoning capabilities that will use thinking tokens.">ⓘ</span>
|
|
223
236
|
</label>
|
|
237
|
+
<label class="register-label reasoning-inline">
|
|
238
|
+
<input type="checkbox" id="register-vision" name="vision">
|
|
239
|
+
Vision
|
|
240
|
+
<span class="tooltip-icon" data-tooltip="Enable to inform Lemonade Server that the model has vision capabilities for processing images.">ⓘ</span>
|
|
241
|
+
</label>
|
|
224
242
|
</div>
|
|
225
243
|
<div class="register-form-row register-form-row-tight">
|
|
226
244
|
<button type="submit" id="register-submit">Install</button>
|
|
@@ -231,6 +249,7 @@
|
|
|
231
249
|
</div>
|
|
232
250
|
</div>
|
|
233
251
|
</div>
|
|
252
|
+
</div>
|
|
234
253
|
</div>
|
|
235
254
|
</main>
|
|
236
255
|
<footer class="site-footer">
|
|
@@ -250,4 +269,3 @@
|
|
|
250
269
|
<script src="/static/js/chat.js"></script>
|
|
251
270
|
</body>
|
|
252
271
|
</html>
|
|
253
|
-
</html>
|