xxx777xxxASD
commited on
Upload 4 files
Browse files- Source Code/QToggle.py +203 -0
- Source Code/main.py +9 -0
- Source Code/ui_loader.py +132 -0
- Source Code/ui_main.py +497 -0
Source Code/QToggle.py
ADDED
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Author: Luan Dias - https://github.com/luandiasrj
|
3 |
+
Url: https://github.com/luandiasrj/QToggle_-_Advanced_QCheckbox_for_PyQT6
|
4 |
+
|
5 |
+
This code implements a custom QToggle class, which is a toggle switch derived
|
6 |
+
from QCheckBox. The QToggle class features customizable colors, and properties.
|
7 |
+
It includes smooth transitions when toggling between states.
|
8 |
+
|
9 |
+
The custom properties include:
|
10 |
+
|
11 |
+
bg_color: background color of the toggle
|
12 |
+
circle_color: color of the circle inside the toggle
|
13 |
+
active_color: color of the background when the toggle is checked
|
14 |
+
disabled_color: color of the toggle when it's disabled
|
15 |
+
text_color: color of the text
|
16 |
+
|
17 |
+
Main functions and methods in the class include:
|
18 |
+
|
19 |
+
init: Initializes the QToggle object with default colors and settings
|
20 |
+
setDuration: Set the duration for the animation
|
21 |
+
update_pos_color: Updates the circle position and background color
|
22 |
+
start_transition: Starts the transition animation when the state changes
|
23 |
+
create_animation: Creates the circle position animation
|
24 |
+
create_bg_color_animation: Creates the background color animation
|
25 |
+
sizeHint: Provides the recommended size for the toggle
|
26 |
+
hitButton: Determines if the mouse click is inside the toggle area
|
27 |
+
paintEvent: Handles the custom painting of the toggle
|
28 |
+
|
29 |
+
The example demonstrates how to use the QToggle class by creating three
|
30 |
+
different toggles with various settings such as custom height, colors, and font.
|
31 |
+
"""
|
32 |
+
|
33 |
+
from PyQt6.QtCore import Qt, QRect, pyqtProperty, QPropertyAnimation, QPoint, \
|
34 |
+
QEasingCurve
|
35 |
+
from PyQt6.QtGui import QColor, QFontMetrics, QPainter, QPainterPath, QBrush, \
|
36 |
+
QPen, QFont
|
37 |
+
from PyQt6.QtWidgets import QApplication, QWidget, QCheckBox, QVBoxLayout
|
38 |
+
|
39 |
+
|
40 |
+
class QToggle(QCheckBox):
|
41 |
+
bg_color = pyqtProperty(
|
42 |
+
QColor, lambda self: self._bg_color,
|
43 |
+
lambda self, col: setattr(self, '_bg_color', col))
|
44 |
+
circle_color = pyqtProperty(
|
45 |
+
QColor, lambda self: self._circle_color,
|
46 |
+
lambda self, col: setattr(self, '_circle_color', col))
|
47 |
+
active_color = pyqtProperty(
|
48 |
+
QColor, lambda self: self._active_color,
|
49 |
+
lambda self, col: setattr(self, '_active_color', col))
|
50 |
+
disabled_color = pyqtProperty(
|
51 |
+
QColor, lambda self: self._disabled_color,
|
52 |
+
lambda self, col: setattr(self, '_disabled_color', col))
|
53 |
+
text_color = pyqtProperty(
|
54 |
+
QColor, lambda self: self._text_color,
|
55 |
+
lambda self, col: setattr(self, '_text_color', col))
|
56 |
+
|
57 |
+
def __init__(self, parent=None):
|
58 |
+
super().__init__(parent)
|
59 |
+
self._bg_color, self._circle_color, self._active_color, \
|
60 |
+
self._disabled_color, self._text_color = QColor("#0BF"), \
|
61 |
+
QColor("#DDD"), QColor('#777'), QColor("#CCC"), QColor("#000")
|
62 |
+
self._circle_pos, self._intermediate_bg_color = None, None
|
63 |
+
self.setFixedHeight(18)
|
64 |
+
self._animation_duration = 500 # milliseconds
|
65 |
+
self.stateChanged.connect(self.start_transition)
|
66 |
+
self._user_checked = False # Introduced flag to check user-initiated changes
|
67 |
+
|
68 |
+
circle_pos = pyqtProperty(
|
69 |
+
float, lambda self: self._circle_pos,
|
70 |
+
lambda self, pos: (setattr(self, '_circle_pos', pos), self.update()))
|
71 |
+
intermediate_bg_color = pyqtProperty(
|
72 |
+
QColor, lambda self: self._intermediate_bg_color,
|
73 |
+
lambda self, col: setattr(self, '_intermediate_bg_color', col))
|
74 |
+
|
75 |
+
def setDuration(self, duration: int):
|
76 |
+
"""
|
77 |
+
Set the duration for the animation.
|
78 |
+
:param duration: Duration in milliseconds.
|
79 |
+
"""
|
80 |
+
self._animation_duration = duration
|
81 |
+
|
82 |
+
def update_pos_color(self, checked=None):
|
83 |
+
self._circle_pos = self.height() * (1.1 if checked else 0.1)
|
84 |
+
if self.isChecked():
|
85 |
+
self._intermediate_bg_color = self._active_color
|
86 |
+
else:
|
87 |
+
self._intermediate_bg_color = self._bg_color
|
88 |
+
|
89 |
+
def start_transition(self, state):
|
90 |
+
if not self._user_checked: # Skip animation if change isn't user-initiated
|
91 |
+
self.update_pos_color(state)
|
92 |
+
return
|
93 |
+
for anim in [self.create_animation, self.create_bg_color_animation]:
|
94 |
+
animation = anim(state)
|
95 |
+
animation.start()
|
96 |
+
self._user_checked = False # Reset the flag after animation starts
|
97 |
+
|
98 |
+
def mousePressEvent(self, event):
|
99 |
+
self._user_checked = True # Set flag when user manually clicks the toggle
|
100 |
+
super().mousePressEvent(event)
|
101 |
+
|
102 |
+
def create_animation(self, state):
|
103 |
+
return self._create_common_animation(
|
104 |
+
state, b'circle_pos', self.height() * 0.1, self.height() * 1.1)
|
105 |
+
|
106 |
+
def create_bg_color_animation(self, state):
|
107 |
+
return self._create_common_animation(
|
108 |
+
state, b'intermediate_bg_color', self._bg_color, self._active_color)
|
109 |
+
|
110 |
+
def _create_common_animation(self, state, prop, start_val, end_val):
|
111 |
+
animation = QPropertyAnimation(self, prop, self)
|
112 |
+
animation.setEasingCurve(QEasingCurve.Type.InOutCubic)
|
113 |
+
animation.setDuration(self._animation_duration)
|
114 |
+
animation.setStartValue(start_val if state else end_val)
|
115 |
+
animation.setEndValue(end_val if state else start_val)
|
116 |
+
return animation
|
117 |
+
|
118 |
+
def showEvent(self, event):
|
119 |
+
super().showEvent(event) # Ensure to call the super class's implementation
|
120 |
+
self.update_pos_color(self.isChecked())
|
121 |
+
|
122 |
+
def resizeEvent(self, event):
|
123 |
+
self.update_pos_color(self.isChecked())
|
124 |
+
|
125 |
+
def sizeHint(self):
|
126 |
+
size = super().sizeHint()
|
127 |
+
text_width = QFontMetrics(
|
128 |
+
self.font()).boundingRect(self.text()).width()
|
129 |
+
size.setWidth(int(self.height() * 2 + text_width * 1.075))
|
130 |
+
return size
|
131 |
+
|
132 |
+
def hitButton(self, pos: QPoint):
|
133 |
+
return self.contentsRect().contains(pos)
|
134 |
+
|
135 |
+
def paintEvent(self, event):
|
136 |
+
painter = QPainter(self)
|
137 |
+
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
138 |
+
|
139 |
+
circle_color = QColor(
|
140 |
+
self.disabled_color if not self.isEnabled() else self.circle_color)
|
141 |
+
bg_color = QColor(
|
142 |
+
self.disabled_color if not self.isEnabled() else
|
143 |
+
self.intermediate_bg_color)
|
144 |
+
text_color = QColor(
|
145 |
+
self.disabled_color if not self.isEnabled() else self.text_color)
|
146 |
+
|
147 |
+
bordersradius = self.height() / 2
|
148 |
+
togglewidth = self.height() * 2
|
149 |
+
togglemargin = self.height() * 0.3
|
150 |
+
circlesize = self.height() * 0.8
|
151 |
+
|
152 |
+
bg_path = QPainterPath()
|
153 |
+
bg_path.addRoundedRect(
|
154 |
+
0, 0, togglewidth, self.height(), bordersradius, bordersradius)
|
155 |
+
painter.fillPath(bg_path, QBrush(bg_color))
|
156 |
+
|
157 |
+
circle = QPainterPath()
|
158 |
+
circle.addEllipse(
|
159 |
+
self.circle_pos, self.height() * 0.1, circlesize, circlesize)
|
160 |
+
painter.fillPath(circle, QBrush(circle_color))
|
161 |
+
|
162 |
+
painter.setPen(QPen(QColor(text_color)))
|
163 |
+
painter.setFont(self.font())
|
164 |
+
text_rect = QRect(int(togglewidth + togglemargin), 0, self.width() -
|
165 |
+
int(togglewidth + togglemargin), self.height())
|
166 |
+
text_rect.adjust(
|
167 |
+
0, (self.height() - painter.fontMetrics().height()) // 2, 0, 0)
|
168 |
+
painter.drawText(text_rect, Qt.AlignmentFlag.AlignLeft |
|
169 |
+
Qt.AlignmentFlag.AlignVCenter, self.text())
|
170 |
+
painter.end()
|
171 |
+
|
172 |
+
|
173 |
+
if __name__ == '__main__':
|
174 |
+
app = QApplication([])
|
175 |
+
window = QWidget()
|
176 |
+
layout = QVBoxLayout()
|
177 |
+
|
178 |
+
checkbox0 = QToggle()
|
179 |
+
checkbox0.setFixedHeight(12)
|
180 |
+
layout.addWidget(checkbox0)
|
181 |
+
|
182 |
+
checkbox1 = QToggle()
|
183 |
+
checkbox1.setText('Checkbox 1 - Disabled')
|
184 |
+
checkbox1.setEnabled(False)
|
185 |
+
layout.addWidget(checkbox1)
|
186 |
+
|
187 |
+
checkbox2 = QToggle()
|
188 |
+
checkbox2.setText('Checkbox 2 - Checked, custom height, animation duration, colors and font')
|
189 |
+
checkbox2.setFixedHeight(24)
|
190 |
+
checkbox2.setFont(QFont('Segoe Print', 10))
|
191 |
+
checkbox2.setStyleSheet("QToggle{"
|
192 |
+
"qproperty-bg_color:#FAA;"
|
193 |
+
"qproperty-circle_color:#DDF;"
|
194 |
+
"qproperty-active_color:#AAF;"
|
195 |
+
"qproperty-disabled_color:#777;"
|
196 |
+
"qproperty-text_color:#A0F;}")
|
197 |
+
checkbox2.setDuration(2000)
|
198 |
+
checkbox2.setChecked(True)
|
199 |
+
layout.addWidget(checkbox2)
|
200 |
+
|
201 |
+
window.setLayout(layout)
|
202 |
+
window.show()
|
203 |
+
app.exec()
|
Source Code/main.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
from PyQt6.QtWidgets import QApplication
|
3 |
+
from ui_loader import UILoader
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
app = QApplication(sys.argv)
|
7 |
+
ui_loader = UILoader()
|
8 |
+
ui_loader.show()
|
9 |
+
sys.exit(app.exec())
|
Source Code/ui_loader.py
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PyQt6.QtWidgets import QMainWindow, QFileDialog
|
2 |
+
from PyQt6.QtCore import Qt
|
3 |
+
from ui_main import Ui_MainWindow
|
4 |
+
import configparser
|
5 |
+
import subprocess
|
6 |
+
import os
|
7 |
+
from PyQt6.QtCore import Qt, QPoint
|
8 |
+
from PyQt6.QtWidgets import QStackedWidget
|
9 |
+
from PyQt6.QtWidgets import QMainWindow, QFileDialog
|
10 |
+
|
11 |
+
class UILoader(QMainWindow, Ui_MainWindow):
|
12 |
+
def __init__(self):
|
13 |
+
super().__init__()
|
14 |
+
self.setupUi(self)
|
15 |
+
self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
|
16 |
+
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
17 |
+
self.init_ui()
|
18 |
+
self.update_batch_size_label(3)
|
19 |
+
self.update_ctx_size_label(4)
|
20 |
+
#self.load_config()
|
21 |
+
self.offset = None # Add this line
|
22 |
+
|
23 |
+
def init_ui(self):
|
24 |
+
self.minimize_button.clicked.connect(self.showMinimized)
|
25 |
+
self.close_button.clicked.connect(self.close)
|
26 |
+
self.model_browse_button.clicked.connect(self.browse_model)
|
27 |
+
self.run_server_button.clicked.connect(self.run_server)
|
28 |
+
self.save_config_button.clicked.connect(self.save_config)
|
29 |
+
self.load_config_button.clicked.connect(self.load_config)
|
30 |
+
|
31 |
+
self.top_bar.mousePressEvent = self.mouse_press_event
|
32 |
+
self.top_bar.mouseMoveEvent = self.mouse_move_event
|
33 |
+
|
34 |
+
def mouse_press_event(self, event):
|
35 |
+
self.offset = event.pos()
|
36 |
+
|
37 |
+
def update_threads_label(self, value):
|
38 |
+
self.threads_label.setText(f"Threads: {value + 1}")
|
39 |
+
|
40 |
+
def mouse_move_event(self, event):
|
41 |
+
if self.offset is not None and event.buttons() == Qt.MouseButton.LeftButton:
|
42 |
+
self.move(self.pos() + event.pos() - self.offset)
|
43 |
+
|
44 |
+
def browse_model(self):
|
45 |
+
model_path, _ = QFileDialog.getOpenFileName(self, "Select Model", os.getcwd(), "Model Files (*.gguf)")
|
46 |
+
self.model_path_line_edit.setText(model_path)
|
47 |
+
|
48 |
+
def run_server(self):
|
49 |
+
model_path = self.model_path_line_edit.text()
|
50 |
+
batch_size = self.batch_size_values[self.batch_size_slider.value()]
|
51 |
+
ctx_size = self.ctx_size_values[self.ctx_size_slider.value()]
|
52 |
+
layers_offload = self.layers_offload_spin_box.value()
|
53 |
+
threads = self.threads_spin_box.value()
|
54 |
+
use_flash_attention = self.flash_attention_checkbox.isChecked()
|
55 |
+
is_moe = self.moe_checkbox.isChecked()
|
56 |
+
moe_experts_string = ""
|
57 |
+
if is_moe:
|
58 |
+
experts_use = self.moe_experts_spin_box.value()
|
59 |
+
moe_experts_string = f"--override-kv llama.expert_used_count=int:{experts_use}"
|
60 |
+
|
61 |
+
custom_rope_freq_base = self.rope_freq_base_spin_box.value() if self.rope_freq_base_checkbox.isChecked() else None
|
62 |
+
mlock = self.mlock_checkbox.isChecked()
|
63 |
+
no_mmap = self.no_mmap_checkbox.isChecked()
|
64 |
+
no_kv_offload = self.no_kv_offload_checkbox.isChecked()
|
65 |
+
|
66 |
+
command = [
|
67 |
+
"LlamaCPP\\llama-server.exe",
|
68 |
+
f"--model {model_path}",
|
69 |
+
f"--batch-size {batch_size}",
|
70 |
+
f"--ctx-size {ctx_size}",
|
71 |
+
f"--n-gpu-layers {layers_offload}",
|
72 |
+
f"--threads {threads}",
|
73 |
+
]
|
74 |
+
|
75 |
+
if use_flash_attention:
|
76 |
+
command.append("--flash-attn")
|
77 |
+
if mlock:
|
78 |
+
command.append("--mlock")
|
79 |
+
if no_mmap:
|
80 |
+
command.append("--no-mmap")
|
81 |
+
if no_kv_offload:
|
82 |
+
command.append("--no-kv-offload")
|
83 |
+
if custom_rope_freq_base is not None:
|
84 |
+
command.append(f"--rope-freq-base {custom_rope_freq_base}")
|
85 |
+
if moe_experts_string:
|
86 |
+
command.append(moe_experts_string)
|
87 |
+
|
88 |
+
print(" ".join(command))
|
89 |
+
subprocess.run(" ".join(command), shell=True)
|
90 |
+
|
91 |
+
def save_config(self):
|
92 |
+
config = configparser.ConfigParser()
|
93 |
+
config["Server"] = {
|
94 |
+
"model_path": self.model_path_line_edit.text(),
|
95 |
+
"batch_size": str(self.batch_size_slider.value()),
|
96 |
+
"ctx_size": str(self.ctx_size_slider.value()),
|
97 |
+
"layers_offload": str(self.layers_offload_spin_box.value()),
|
98 |
+
"threads": str(self.threads_spin_box.value()),
|
99 |
+
"use_flash_attention": str(self.flash_attention_checkbox.isChecked()),
|
100 |
+
"is_moe": str(self.moe_checkbox.isChecked()),
|
101 |
+
"moe_experts": str(self.moe_experts_spin_box.value()),
|
102 |
+
"rope_freq_base_custom": str(self.rope_freq_base_checkbox.isChecked()),
|
103 |
+
"rope_freq_base_value": str(self.rope_freq_base_spin_box.value()),
|
104 |
+
"mlock": str(self.mlock_checkbox.isChecked()),
|
105 |
+
"no_mmap": str(self.no_mmap_checkbox.isChecked()),
|
106 |
+
"no_kv_offload": str(self.no_kv_offload_checkbox.isChecked()),
|
107 |
+
}
|
108 |
+
|
109 |
+
file_path, _ = QFileDialog.getSaveFileName(self, "Save Configuration", os.getcwd(), "INI Files (*.ini)")
|
110 |
+
if file_path:
|
111 |
+
with open(file_path, "w") as config_file:
|
112 |
+
config.write(config_file)
|
113 |
+
|
114 |
+
def load_config(self):
|
115 |
+
file_path, _ = QFileDialog.getOpenFileName(self, "Load Configuration", os.getcwd(), "INI Files (*.ini)")
|
116 |
+
if file_path:
|
117 |
+
config = configparser.ConfigParser()
|
118 |
+
config.read(file_path)
|
119 |
+
|
120 |
+
self.model_path_line_edit.setText(config.get("Server", "model_path", fallback=""))
|
121 |
+
self.batch_size_slider.setValue(config.getint("Server", "batch_size", fallback=512))
|
122 |
+
self.ctx_size_slider.setValue(config.getint("Server", "ctx_size", fallback=8192))
|
123 |
+
self.layers_offload_spin_box.setValue(config.getint("Server", "layers_offload", fallback=22))
|
124 |
+
self.threads_spin_box.setValue(config.getint("Server", "threads", fallback=14))
|
125 |
+
self.flash_attention_checkbox.setChecked(config.getboolean("Server", "use_flash_attention", fallback=False))
|
126 |
+
self.moe_checkbox.setChecked(config.getboolean("Server", "is_moe", fallback=False))
|
127 |
+
self.moe_experts_spin_box.setValue(config.getint("Server", "moe_experts", fallback=1))
|
128 |
+
self.rope_freq_base_checkbox.setChecked(config.getboolean("Server", "rope_freq_base_custom", fallback=False))
|
129 |
+
self.rope_freq_base_spin_box.setValue(config.getint("Server", "rope_freq_base_value", fallback=1))
|
130 |
+
self.mlock_checkbox.setChecked(config.getboolean("Server", "mlock", fallback=False))
|
131 |
+
self.no_mmap_checkbox.setChecked(config.getboolean("Server", "no_mmap", fallback=False))
|
132 |
+
self.no_kv_offload_checkbox.setChecked(config.getboolean("Server", "no_kv_offload", fallback=False))
|
Source Code/ui_main.py
ADDED
@@ -0,0 +1,497 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PyQt6 import QtCore, QtGui, QtWidgets
|
2 |
+
import os
|
3 |
+
from QToggle import QToggle
|
4 |
+
|
5 |
+
class FixedValueSlider(QtWidgets.QSlider):
|
6 |
+
def __init__(self, values, parent=None):
|
7 |
+
super().__init__(QtCore.Qt.Orientation.Horizontal, parent)
|
8 |
+
self.setMinimum(0)
|
9 |
+
self.setMaximum(len(values) - 1)
|
10 |
+
self.setTickPosition(QtWidgets.QSlider.TickPosition.TicksBelow)
|
11 |
+
self.setTickInterval(1)
|
12 |
+
self.values = values
|
13 |
+
self.valueChanged.connect(self.update_value_label)
|
14 |
+
|
15 |
+
def value(self):
|
16 |
+
return self.values[super().value()]
|
17 |
+
|
18 |
+
def setValue(self, value):
|
19 |
+
super().setValue(self.values.index(value))
|
20 |
+
|
21 |
+
def update_value_label(self, index):
|
22 |
+
self.valueChanged.emit(self.values[index])
|
23 |
+
|
24 |
+
class Ui_MainWindow(object):
|
25 |
+
def retranslateUi(self, MainWindow):
|
26 |
+
_translate = QtCore.QCoreApplication.translate
|
27 |
+
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
28 |
+
self.title_label.setText(_translate("MainWindow", " 🔵 LLAMACPP SERVER UI"))
|
29 |
+
self.minimize_button.setText(_translate("MainWindow", "-"))
|
30 |
+
self.close_button.setText(_translate("MainWindow", "X"))
|
31 |
+
self.model_path_label.setText(_translate("MainWindow", "Model Path:"))
|
32 |
+
self.model_browse_button.setText(_translate("MainWindow", "Browse"))
|
33 |
+
self.batch_size_label.setText(_translate("MainWindow", "Batch Size:"))
|
34 |
+
self.ctx_size_label.setText(_translate("MainWindow", "Context Size:"))
|
35 |
+
self.layers_offload_label.setText(_translate("MainWindow", "Layers Offload:"))
|
36 |
+
self.threads_label.setText(_translate("MainWindow", "Threads:"))
|
37 |
+
self.flash_attention_checkbox.setText(_translate("MainWindow", "Flash Attention"))
|
38 |
+
self.moe_checkbox.setText(_translate("MainWindow", "Custom MoE Experts"))
|
39 |
+
self.moe_experts_label.setText(_translate("MainWindow", "MoE Active Experts:"))
|
40 |
+
self.rope_freq_base_checkbox.setText(_translate("MainWindow", "Custom RoPE Freq Base"))
|
41 |
+
self.rope_freq_base_label.setText(_translate("MainWindow", "RoPE Freq Base:"))
|
42 |
+
self.mlock_checkbox.setText(_translate("MainWindow", "Use mlock"))
|
43 |
+
self.no_mmap_checkbox.setText(_translate("MainWindow", "Disable MMAP"))
|
44 |
+
self.no_kv_offload_checkbox.setText(_translate("MainWindow", "No KV Offload"))
|
45 |
+
self.run_server_button.setText(_translate("MainWindow", "Run Server"))
|
46 |
+
self.save_config_button.setText(_translate("MainWindow", "Save Config"))
|
47 |
+
self.load_config_button.setText(_translate("MainWindow", "Load Config"))
|
48 |
+
|
49 |
+
def update_batch_size_label(self, value):
|
50 |
+
self.batch_size_label.setText(f"Batch Size: {self.batch_size_values[value]}")
|
51 |
+
|
52 |
+
def update_ctx_size_label(self, value):
|
53 |
+
self.ctx_size_label.setText(f"Context Size: {self.ctx_size_values[value]}")
|
54 |
+
|
55 |
+
def setupUi(self, MainWindow):
|
56 |
+
MainWindow.setObjectName("MainWindow")
|
57 |
+
MainWindow.resize(800, 600)
|
58 |
+
|
59 |
+
|
60 |
+
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
61 |
+
self.centralwidget.setObjectName("centralwidget")
|
62 |
+
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
63 |
+
self.verticalLayout.setObjectName("verticalLayout")
|
64 |
+
self.top_bar = QtWidgets.QFrame(self.centralwidget)
|
65 |
+
self.top_bar.setMaximumSize(QtCore.QSize(16777215, 40))
|
66 |
+
self.top_bar.setStyleSheet("background-color: #2c313c;")
|
67 |
+
self.top_bar.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
|
68 |
+
self.top_bar.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
|
69 |
+
self.top_bar.setObjectName("top_bar")
|
70 |
+
self.horizontalLayout = QtWidgets.QHBoxLayout(self.top_bar)
|
71 |
+
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
|
72 |
+
self.horizontalLayout.setSpacing(0)
|
73 |
+
self.horizontalLayout.setObjectName("horizontalLayout")
|
74 |
+
|
75 |
+
#TITLE LABEL
|
76 |
+
self.title_label = QtWidgets.QLabel(self.top_bar)
|
77 |
+
font = QtGui.QFont()
|
78 |
+
font.setPointSize(10)
|
79 |
+
font.setBold(True)
|
80 |
+
self.title_label.setFont(font)
|
81 |
+
self.title_label.setStyleSheet("color: white;")
|
82 |
+
self.title_label.setObjectName("title_label")
|
83 |
+
self.horizontalLayout.addWidget(self.title_label)
|
84 |
+
self.minimize_button = QtWidgets.QPushButton(self.top_bar)
|
85 |
+
self.minimize_button.setMaximumSize(QtCore.QSize(30, 30))
|
86 |
+
self.minimize_button.setStyleSheet("QPushButton {\n"
|
87 |
+
" background-color: #2c313c;\n"
|
88 |
+
" border: none;\n"
|
89 |
+
" color: white;\n"
|
90 |
+
"}\n"
|
91 |
+
"\n"
|
92 |
+
"QPushButton:hover {\n"
|
93 |
+
" background-color: #495057;\n"
|
94 |
+
"}\n"
|
95 |
+
"\n"
|
96 |
+
"QPushButton:pressed {\n"
|
97 |
+
" background-color: #6c757d;\n"
|
98 |
+
"}")
|
99 |
+
self.minimize_button.setObjectName("minimize_button")
|
100 |
+
self.horizontalLayout.addWidget(self.minimize_button)
|
101 |
+
self.close_button = QtWidgets.QPushButton(self.top_bar)
|
102 |
+
self.close_button.setMaximumSize(QtCore.QSize(30, 30))
|
103 |
+
self.close_button.setStyleSheet("QPushButton {\n"
|
104 |
+
" background-color: #2c313c;\n"
|
105 |
+
" border: none;\n"
|
106 |
+
" color: white;\n"
|
107 |
+
"}\n"
|
108 |
+
"\n"
|
109 |
+
"QPushButton:hover {\n"
|
110 |
+
" background-color: #dc3545;\n"
|
111 |
+
"}\n"
|
112 |
+
"\n"
|
113 |
+
"QPushButton:pressed {\n"
|
114 |
+
" background-color: #c82333;\n"
|
115 |
+
"}")
|
116 |
+
self.close_button.setObjectName("close_button")
|
117 |
+
self.horizontalLayout.addWidget(self.close_button)
|
118 |
+
self.verticalLayout.addWidget(self.top_bar)
|
119 |
+
self.content_area = QtWidgets.QFrame(self.centralwidget)
|
120 |
+
self.content_area.setStyleSheet("background-color: #212529;")
|
121 |
+
self.content_area.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
|
122 |
+
self.content_area.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
|
123 |
+
self.content_area.setObjectName("content_area")
|
124 |
+
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.content_area)
|
125 |
+
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
126 |
+
self.model_path_layout = QtWidgets.QHBoxLayout()
|
127 |
+
self.model_path_layout.setObjectName("model_path_layout")
|
128 |
+
self.model_path_label = QtWidgets.QLabel(self.content_area)
|
129 |
+
font = QtGui.QFont()
|
130 |
+
font.setPointSize(10)
|
131 |
+
self.model_path_label.setFont(font)
|
132 |
+
self.model_path_label.setStyleSheet("color: white;")
|
133 |
+
self.model_path_label.setObjectName("model_path_label")
|
134 |
+
self.model_path_layout.addWidget(self.model_path_label)
|
135 |
+
self.model_path_line_edit = QtWidgets.QLineEdit(self.content_area)
|
136 |
+
self.model_path_line_edit.setStyleSheet("background-color: #495057;\n"
|
137 |
+
"color: white;\n"
|
138 |
+
"border-radius: 8px;\n"
|
139 |
+
"padding: 5px;")
|
140 |
+
self.model_path_line_edit.setObjectName("model_path_line_edit")
|
141 |
+
self.model_path_layout.addWidget(self.model_path_line_edit)
|
142 |
+
self.model_browse_button = QtWidgets.QPushButton(self.content_area)
|
143 |
+
self.model_browse_button.setStyleSheet("QPushButton {\n"
|
144 |
+
" background-color: #495057;\n"
|
145 |
+
" color: white;\n"
|
146 |
+
" border-radius: 8px;\n"
|
147 |
+
" padding: 5px;\n"
|
148 |
+
"}\n"
|
149 |
+
"\n"
|
150 |
+
"QPushButton:hover {\n"
|
151 |
+
" background-color: #6c757d;\n"
|
152 |
+
"}\n"
|
153 |
+
"\n"
|
154 |
+
"QPushButton:pressed {\n"
|
155 |
+
" background-color: #343a40;\n"
|
156 |
+
"}")
|
157 |
+
self.model_browse_button.setObjectName("model_browse_button")
|
158 |
+
self.model_path_layout.addWidget(self.model_browse_button)
|
159 |
+
self.verticalLayout_2.addLayout(self.model_path_layout)
|
160 |
+
self.settings_layout = QtWidgets.QGridLayout()
|
161 |
+
self.settings_layout.setObjectName("settings_layout")
|
162 |
+
|
163 |
+
|
164 |
+
|
165 |
+
############
|
166 |
+
# BATCH SIZE/ CTX
|
167 |
+
############
|
168 |
+
|
169 |
+
self.batch_size_label = QtWidgets.QLabel(self.content_area)
|
170 |
+
font = QtGui.QFont()
|
171 |
+
font.setPointSize(10)
|
172 |
+
self.batch_size_label.setFont(font)
|
173 |
+
self.batch_size_label.setStyleSheet("color: white;")
|
174 |
+
self.batch_size_label.setObjectName("batch_size_label")
|
175 |
+
self.settings_layout.addWidget(self.batch_size_label, 0, 0, 1, 1)
|
176 |
+
|
177 |
+
self.batch_size_slider = QtWidgets.QSlider(self.content_area)
|
178 |
+
self.batch_size_slider.setStyleSheet("QSlider::groove:horizontal {\n"
|
179 |
+
" background-color: #495057;\n"
|
180 |
+
" height: 10px;\n"
|
181 |
+
"}\n"
|
182 |
+
"\n"
|
183 |
+
"QSlider::handle:horizontal {\n"
|
184 |
+
" background-color: white;\n"
|
185 |
+
" width: 20px;\n"
|
186 |
+
" border-radius: 5px;\n"
|
187 |
+
" margin: -5px 0;\n"
|
188 |
+
"}")
|
189 |
+
self.batch_size_slider.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
190 |
+
self.batch_size_slider.setMinimum(0)
|
191 |
+
self.batch_size_slider.setMaximum(4)
|
192 |
+
self.batch_size_slider.setTickPosition(QtWidgets.QSlider.TickPosition.TicksBelow)
|
193 |
+
self.batch_size_slider.setTickInterval(1)
|
194 |
+
self.batch_size_values = [64, 128, 256, 512, 1024]
|
195 |
+
self.batch_size_slider.valueChanged.connect(self.update_batch_size_label)
|
196 |
+
self.batch_size_slider.setProperty("value", 3)
|
197 |
+
self.settings_layout.addWidget(self.batch_size_slider, 0, 1, 1, 3)
|
198 |
+
|
199 |
+
self.ctx_size_label = QtWidgets.QLabel(self.content_area)
|
200 |
+
font = QtGui.QFont()
|
201 |
+
font.setPointSize(10)
|
202 |
+
self.ctx_size_label.setFont(font)
|
203 |
+
self.ctx_size_label.setStyleSheet("color: white;")
|
204 |
+
self.ctx_size_label.setObjectName("ctx_size_label")
|
205 |
+
self.settings_layout.addWidget(self.ctx_size_label, 1, 0, 1, 3)
|
206 |
+
|
207 |
+
self.ctx_size_slider = QtWidgets.QSlider(self.content_area)
|
208 |
+
self.ctx_size_slider.setStyleSheet("QSlider::groove:horizontal {\n"
|
209 |
+
" background-color: #495057;\n"
|
210 |
+
" height: 10px;\n"
|
211 |
+
"}\n"
|
212 |
+
"\n"
|
213 |
+
"QSlider::handle:horizontal {\n"
|
214 |
+
" background-color: white;\n"
|
215 |
+
" width: 20px;\n"
|
216 |
+
" border-radius: 5px;\n"
|
217 |
+
" margin: -5px 0;\n"
|
218 |
+
"}")
|
219 |
+
self.ctx_size_slider.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
220 |
+
self.ctx_size_slider.setMinimum(0)
|
221 |
+
self.ctx_size_slider.setMaximum(64)
|
222 |
+
|
223 |
+
self.ctx_size_slider.setTickPosition(QtWidgets.QSlider.TickPosition.TicksBelow)
|
224 |
+
self.ctx_size_slider.setTickInterval(1)
|
225 |
+
self.ctx_size_values = [1024 * (i) for i in range(65)]
|
226 |
+
self.ctx_size_slider.valueChanged.connect(self.update_ctx_size_label)
|
227 |
+
self.ctx_size_slider.setProperty("value", 4)
|
228 |
+
self.settings_layout.addWidget(self.ctx_size_slider, 1, 1, 1, 3)
|
229 |
+
|
230 |
+
############
|
231 |
+
# UI THREADS / LAYERS
|
232 |
+
############
|
233 |
+
|
234 |
+
# GPU OFFLOAD
|
235 |
+
self.layers_offload_label = QtWidgets.QLabel(self.content_area)
|
236 |
+
font = QtGui.QFont()
|
237 |
+
font.setPointSize(10)
|
238 |
+
self.layers_offload_label.setFont(font)
|
239 |
+
self.layers_offload_label.setStyleSheet("color: white;")
|
240 |
+
self.layers_offload_label.setObjectName("layers_offload_label")
|
241 |
+
self.settings_layout.addWidget(self.layers_offload_label, 2, 0, 1, 1)
|
242 |
+
self.layers_offload_spin_box = QtWidgets.QSpinBox(self.content_area)
|
243 |
+
self.layers_offload_spin_box.setStyleSheet("background-color: #495057;\n"
|
244 |
+
"color: white;\n"
|
245 |
+
"border-radius: 8px;\n"
|
246 |
+
"padding: 5px;")
|
247 |
+
self.layers_offload_spin_box.setMinimum(0)
|
248 |
+
self.layers_offload_spin_box.setMaximum(200)
|
249 |
+
self.layers_offload_spin_box.setProperty("value", 0)
|
250 |
+
self.layers_offload_spin_box.setObjectName("layers_offload_spin_box")
|
251 |
+
self.settings_layout.addWidget(self.layers_offload_spin_box, 2, 1, 1, 1)
|
252 |
+
|
253 |
+
|
254 |
+
# THREADS
|
255 |
+
self.threads_label = QtWidgets.QLabel(self.content_area)
|
256 |
+
font = QtGui.QFont()
|
257 |
+
font.setPointSize(10)
|
258 |
+
self.threads_label.setFont(font)
|
259 |
+
self.threads_label.setStyleSheet("color: white;")
|
260 |
+
self.threads_label.setObjectName("threads_label")
|
261 |
+
self.settings_layout.addWidget(self.threads_label, 2, 2, 1, 1)
|
262 |
+
|
263 |
+
self.threads_spin_box = QtWidgets.QSpinBox(self.content_area)
|
264 |
+
self.threads_spin_box.setStyleSheet("background-color: #495057;\n"
|
265 |
+
"color: white;\n"
|
266 |
+
"border-radius: 8px;\n"
|
267 |
+
"padding: 5px;")
|
268 |
+
self.threads_spin_box.setMinimum(0)
|
269 |
+
self.threads_spin_box.setMaximum(os.cpu_count())
|
270 |
+
self.threads_spin_box.setProperty("value", int(os.cpu_count()/2))
|
271 |
+
self.threads_spin_box.setObjectName("threads_spin_box")
|
272 |
+
self.settings_layout.addWidget(self.threads_spin_box, 2, 3, 1, 1)
|
273 |
+
|
274 |
+
|
275 |
+
|
276 |
+
|
277 |
+
###
|
278 |
+
self.verticalLayout_2.addLayout(self.settings_layout)
|
279 |
+
self.advanced_options_layout = QtWidgets.QGridLayout()
|
280 |
+
self.advanced_options_layout.setObjectName("advanced_options_layout")
|
281 |
+
###
|
282 |
+
|
283 |
+
|
284 |
+
|
285 |
+
|
286 |
+
|
287 |
+
############
|
288 |
+
# UI MOE
|
289 |
+
############
|
290 |
+
self.moe_checkbox = QToggle()
|
291 |
+
self.moe_checkbox.setFixedHeight(20)
|
292 |
+
self.moe_checkbox.setDuration(250)
|
293 |
+
self.moe_checkbox.setStyleSheet("QToggle{"
|
294 |
+
"qproperty-bg_color:#495057;"
|
295 |
+
"qproperty-circle_color:#FFF;"
|
296 |
+
"qproperty-active_color:#0066ff;"
|
297 |
+
"qproperty-disabled_color:#383838;"
|
298 |
+
"qproperty-text_color:#FFF;}")
|
299 |
+
|
300 |
+
self.moe_checkbox.setObjectName("moe_checkbox")
|
301 |
+
self.advanced_options_layout.addWidget(self.moe_checkbox, 0, 0, 1, 1)
|
302 |
+
|
303 |
+
|
304 |
+
|
305 |
+
self.moe_experts_label = QtWidgets.QLabel(self.content_area)
|
306 |
+
font = QtGui.QFont()
|
307 |
+
font.setPointSize(10)
|
308 |
+
self.moe_experts_label.setFont(font)
|
309 |
+
self.moe_experts_label.setStyleSheet("color: white;")
|
310 |
+
self.moe_experts_label.setObjectName("moe_experts_label")
|
311 |
+
self.advanced_options_layout.addWidget(self.moe_experts_label, 0, 2, 1, 1)
|
312 |
+
self.moe_experts_spin_box = QtWidgets.QSpinBox(self.content_area)
|
313 |
+
self.moe_experts_spin_box.setStyleSheet("background-color: #495057;\n"
|
314 |
+
"color: white;\n"
|
315 |
+
"border-radius: 8px;\n"
|
316 |
+
"padding: 5px;")
|
317 |
+
self.moe_experts_spin_box.setMinimum(1)
|
318 |
+
self.moe_experts_spin_box.setMaximum(32)
|
319 |
+
self.moe_experts_spin_box.setProperty("value", 2)
|
320 |
+
self.moe_experts_spin_box.setObjectName("moe_experts_spin_box")
|
321 |
+
self.advanced_options_layout.addWidget(self.moe_experts_spin_box, 0, 3, 1, 1)
|
322 |
+
|
323 |
+
############
|
324 |
+
# UI ROPE FREQ BASE
|
325 |
+
############
|
326 |
+
# CUSTOM ROPE FREQ BASE CHECKBOX
|
327 |
+
self.rope_freq_base_checkbox = QToggle()
|
328 |
+
self.rope_freq_base_checkbox.setFixedHeight(20)
|
329 |
+
self.rope_freq_base_checkbox.setDuration(250)
|
330 |
+
self.rope_freq_base_checkbox.setStyleSheet("QToggle{"
|
331 |
+
"qproperty-bg_color:#495057;"
|
332 |
+
"qproperty-circle_color:#FFF;"
|
333 |
+
"qproperty-active_color:#0066ff;"
|
334 |
+
"qproperty-disabled_color:#383838;"
|
335 |
+
"qproperty-text_color:#FFF;}")
|
336 |
+
self.rope_freq_base_checkbox.setObjectName("rope_freq_base_checkbox")
|
337 |
+
self.advanced_options_layout.addWidget(self.rope_freq_base_checkbox, 1, 0, 1, 1)
|
338 |
+
|
339 |
+
# CUSTOM ROPE FREQ BASE LABEL
|
340 |
+
self.rope_freq_base_label = QtWidgets.QLabel(self.content_area)
|
341 |
+
font = QtGui.QFont()
|
342 |
+
font.setPointSize(10)
|
343 |
+
self.rope_freq_base_label.setFont(font)
|
344 |
+
self.rope_freq_base_label.setStyleSheet("color: white;")
|
345 |
+
self.rope_freq_base_label.setObjectName("rope_freq_base_label")
|
346 |
+
self.advanced_options_layout.addWidget(self.rope_freq_base_label, 1, 2, 1, 1)
|
347 |
+
self.rope_freq_base_spin_box = QtWidgets.QSpinBox(self.content_area)
|
348 |
+
self.rope_freq_base_spin_box.setStyleSheet("background-color: #495057;\n"
|
349 |
+
"color: white;\n"
|
350 |
+
"border-radius: 8px;\n"
|
351 |
+
"padding: 5px;")
|
352 |
+
self.rope_freq_base_spin_box.setMinimum(1)
|
353 |
+
self.rope_freq_base_spin_box.setMaximum(1000)
|
354 |
+
self.rope_freq_base_spin_box.setProperty("value", 1)
|
355 |
+
self.rope_freq_base_spin_box.setObjectName("rope_freq_base_spin_box")
|
356 |
+
self.advanced_options_layout.addWidget(self.rope_freq_base_spin_box, 1, 3, 1, 1)
|
357 |
+
|
358 |
+
|
359 |
+
|
360 |
+
############
|
361 |
+
# UI ADDITIONAL
|
362 |
+
############
|
363 |
+
|
364 |
+
# FLASH ATTENTION CHECKBOX
|
365 |
+
self.flash_attention_checkbox = QToggle()
|
366 |
+
self.flash_attention_checkbox.setFixedHeight(20)
|
367 |
+
self.flash_attention_checkbox.setDuration(250)
|
368 |
+
self.flash_attention_checkbox.setStyleSheet("QToggle{"
|
369 |
+
"qproperty-bg_color:#495057;"
|
370 |
+
"qproperty-circle_color:#FFF;"
|
371 |
+
"qproperty-active_color:#0066ff;"
|
372 |
+
"qproperty-disabled_color:#383838;"
|
373 |
+
"qproperty-text_color:#FFF;}")
|
374 |
+
|
375 |
+
self.flash_attention_checkbox.setObjectName("flash_attention_checkbox")
|
376 |
+
self.advanced_options_layout.addWidget(self.flash_attention_checkbox, 2, 3, 1, 1)
|
377 |
+
|
378 |
+
# MLOCK CHECKBOX
|
379 |
+
self.mlock_checkbox = QToggle()
|
380 |
+
self.mlock_checkbox.setFixedHeight(20)
|
381 |
+
self.mlock_checkbox.setDuration(250)
|
382 |
+
self.mlock_checkbox.setStyleSheet("QToggle{"
|
383 |
+
"qproperty-bg_color:#495057;"
|
384 |
+
"qproperty-circle_color:#FFF;"
|
385 |
+
"qproperty-active_color:#0066ff;"
|
386 |
+
"qproperty-disabled_color:#383838;"
|
387 |
+
"qproperty-text_color:#FFF;}")
|
388 |
+
self.mlock_checkbox.setObjectName("mlock_checkbox")
|
389 |
+
self.advanced_options_layout.addWidget(self.mlock_checkbox, 2, 0, 1, 1)
|
390 |
+
|
391 |
+
# NO MMAP CHECKBOX
|
392 |
+
self.no_mmap_checkbox = QToggle()
|
393 |
+
self.no_mmap_checkbox.setFixedHeight(20)
|
394 |
+
self.no_mmap_checkbox.setDuration(250)
|
395 |
+
self.no_mmap_checkbox.setStyleSheet("QToggle{"
|
396 |
+
"qproperty-bg_color:#495057;"
|
397 |
+
"qproperty-circle_color:#FFF;"
|
398 |
+
"qproperty-active_color:#0066ff;"
|
399 |
+
"qproperty-disabled_color:#383838;"
|
400 |
+
"qproperty-text_color:#FFF;}")
|
401 |
+
|
402 |
+
self.no_mmap_checkbox.setObjectName("no_mmap_checkbox")
|
403 |
+
self.advanced_options_layout.addWidget(self.no_mmap_checkbox, 2, 1, 1, 1)
|
404 |
+
|
405 |
+
# NO KV OFFLOAD CHECKBOX
|
406 |
+
self.no_kv_offload_checkbox = QToggle()
|
407 |
+
self.no_kv_offload_checkbox.setFixedHeight(20)
|
408 |
+
self.no_kv_offload_checkbox.setDuration(250)
|
409 |
+
self.no_kv_offload_checkbox.setStyleSheet("QToggle{"
|
410 |
+
"qproperty-bg_color:#495057;"
|
411 |
+
"qproperty-circle_color:#FFF;"
|
412 |
+
"qproperty-active_color:#0066ff;"
|
413 |
+
"qproperty-disabled_color:#383838;"
|
414 |
+
"qproperty-text_color:#FFF;}")
|
415 |
+
|
416 |
+
self.no_kv_offload_checkbox.setObjectName("no_kv_offload_checkbox")
|
417 |
+
self.advanced_options_layout.addWidget(self.no_kv_offload_checkbox, 2, 2, 1, 1)
|
418 |
+
|
419 |
+
|
420 |
+
|
421 |
+
|
422 |
+
|
423 |
+
|
424 |
+
|
425 |
+
|
426 |
+
|
427 |
+
|
428 |
+
|
429 |
+
|
430 |
+
##################################
|
431 |
+
# DOWN BUTTONS
|
432 |
+
##################################
|
433 |
+
self.verticalLayout_2.addLayout(self.advanced_options_layout)
|
434 |
+
self.run_server_button = QtWidgets.QPushButton(self.content_area)
|
435 |
+
self.run_server_button.setStyleSheet("QPushButton {\n"
|
436 |
+
" background-color: #0066ff;\n"
|
437 |
+
" color: white;\n"
|
438 |
+
" padding: 10px;\n"
|
439 |
+
" border-radius: 8px;\n"
|
440 |
+
" font-size: 16px;\n"
|
441 |
+
"}\n"
|
442 |
+
"\n"
|
443 |
+
"QPushButton:hover {\n"
|
444 |
+
" background-color: #1774ff;\n"
|
445 |
+
|
446 |
+
|
447 |
+
"}\n"
|
448 |
+
"\n"
|
449 |
+
"QPushButton:pressed {\n"
|
450 |
+
" background-color: #0049b8;\n"
|
451 |
+
"}")
|
452 |
+
self.run_server_button.setObjectName("run_server_button")
|
453 |
+
self.verticalLayout_2.addWidget(self.run_server_button)
|
454 |
+
self.config_layout = QtWidgets.QHBoxLayout()
|
455 |
+
self.config_layout.setObjectName("config_layout")
|
456 |
+
self.save_config_button = QtWidgets.QPushButton(self.content_area)
|
457 |
+
self.save_config_button.setStyleSheet("QPushButton {\n"
|
458 |
+
" background-color: #2e82ff;\n"
|
459 |
+
" color: white;\n"
|
460 |
+
" border-radius: 8px;\n"
|
461 |
+
" padding: 5px;\n"
|
462 |
+
"}\n"
|
463 |
+
"\n"
|
464 |
+
"QPushButton:hover {\n"
|
465 |
+
" background-color: #428eff;\n"
|
466 |
+
"}\n"
|
467 |
+
"\n"
|
468 |
+
"QPushButton:pressed {\n"
|
469 |
+
" background-color: #1e6ce3;\n"
|
470 |
+
"}")
|
471 |
+
self.save_config_button.setObjectName("save_config_button")
|
472 |
+
self.config_layout.addWidget(self.save_config_button)
|
473 |
+
self.load_config_button = QtWidgets.QPushButton(self.content_area)
|
474 |
+
self.load_config_button.setStyleSheet("QPushButton {\n"
|
475 |
+
" background-color: #2e82ff;\n"
|
476 |
+
" color: white;\n"
|
477 |
+
" border-radius: 8px;\n"
|
478 |
+
" padding: 5px;\n"
|
479 |
+
"}\n"
|
480 |
+
"\n"
|
481 |
+
"QPushButton:hover {\n"
|
482 |
+
" background-color: #428eff;\n"
|
483 |
+
"}\n"
|
484 |
+
"\n"
|
485 |
+
"QPushButton:pressed {\n"
|
486 |
+
" background-color: #1e6ce3;\n"
|
487 |
+
"}")
|
488 |
+
self.load_config_button.setObjectName("load_config_button")
|
489 |
+
self.config_layout.addWidget(self.load_config_button)
|
490 |
+
self.verticalLayout_2.addLayout(self.config_layout)
|
491 |
+
self.verticalLayout.addWidget(self.content_area)
|
492 |
+
MainWindow.setCentralWidget(self.centralwidget)
|
493 |
+
|
494 |
+
self.retranslateUi(MainWindow)
|
495 |
+
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
496 |
+
|
497 |
+
|