some UI tweaks

This commit is contained in:
Radek Davidek 2026-04-22 17:01:38 +02:00
parent 9283f4e766
commit 9f909192d2
4 changed files with 145 additions and 142 deletions

View File

@ -1,5 +1,6 @@
#Llama Runner Configuration #Llama Runner Configuration
#Tue Apr 14 16:56:36 CEST 2026 #Wed Apr 22 16:58:54 CEST 2026
lastProfile=Exaone4
windowHeight=1281 windowHeight=1281
windowWidth=665 windowWidth=665
windowX=1895 windowX=1895

View File

@ -21,28 +21,6 @@
"fit": false, "fit": false,
"reasoning": false "reasoning": false
}, },
"Qwen3.5-q6k-180k": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.6,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 180000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.5-35B-A3B-Q6_K.gguf",
"chatTemplateKwargs": "{\"enable_thinking\": false}",
"ngl": 999,
"fit": true,
"reasoning": false
},
"QwenCoderNext-160k": { "QwenCoderNext-160k": {
"host": "0.0.0.0", "host": "0.0.0.0",
"port": 3080, "port": 3080,
@ -87,28 +65,6 @@
"fit": false, "fit": false,
"reasoning": false "reasoning": false
}, },
"Qwen3.5 q6xl 160k": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "turbo3",
"cacheTypeV": "turbo3",
"temperature": 0.6,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 160000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.5-35B-A3B-UD-Q6_K_XL.gguf",
"chatTemplateKwargs": "{\"enable_thinking\": false}",
"ngl": -1,
"fit": true,
"reasoning": false
},
"gpt-oss-20b-160k": { "gpt-oss-20b-160k": {
"host": "0.0.0.0", "host": "0.0.0.0",
"port": 3080, "port": 3080,
@ -175,46 +131,24 @@
"fit": true, "fit": true,
"reasoning": false "reasoning": false
}, },
"Qwen3-Coder-Next-UD-Q2KXL-160k": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "turbo3",
"cacheTypeV": "turbo3",
"temperature": 0.6,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 160000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3-Coder-Next-UD-Q2_K_XL.gguf",
"chatTemplateKwargs": "{\"enable_thinking\": true}",
"ngl": -1,
"fit": true,
"reasoning": false
},
"Qwen3-Coder-Next-UD-Q3KXL-160k": { "Qwen3-Coder-Next-UD-Q3KXL-160k": {
"host": "0.0.0.0", "host": "0.0.0.0",
"port": 3080, "port": 3080,
"parallel": 1, "parallel": 1,
"batchSize": 2048, "batchSize": 4096,
"threads": 99, "threads": 99,
"flashAttention": true, "flashAttention": true,
"kvUnified": true, "kvUnified": true,
"cacheTypeK": "turbo3", "cacheTypeK": "q8_0",
"cacheTypeV": "turbo3", "cacheTypeV": "q8_0",
"temperature": 0.6, "temperature": 1.0,
"topP": 0.95, "topP": 0.95,
"topK": 20, "topK": 40,
"minP": 0.0, "minP": 0.01,
"ctxSize": 160000, "ctxSize": 160000,
"enableThinking": false, "enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3-Coder-Next-UD-Q3_K_XL.gguf", "modelPath": "/home/kamma/models/Qwen3-Coder-Next-UD-Q3_K_XL.gguf",
"chatTemplateKwargs": "{\"enable_thinking\": true}", "chatTemplateKwargs": "",
"ngl": -1, "ngl": -1,
"fit": true, "fit": true,
"reasoning": false "reasoning": false
@ -227,63 +161,19 @@
"threads": 99, "threads": 99,
"flashAttention": true, "flashAttention": true,
"kvUnified": true, "kvUnified": true,
"cacheTypeK": "turbo3", "cacheTypeK": "q8_0",
"cacheTypeV": "turbo3", "cacheTypeV": "q8_0",
"temperature": 0.6, "temperature": 1.0,
"topP": 0.95, "topP": 0.95,
"topK": 20, "topK": 40,
"minP": 0.0, "minP": 0.01,
"ctxSize": 160000, "ctxSize": 160000,
"enableThinking": false, "enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3-Coder-Next-UD-Q4_K_XL.gguf", "modelPath": "/home/kamma/models/Qwen3-Coder-Next-UD-Q4_K_XL.gguf",
"chatTemplateKwargs": "", "chatTemplateKwargs": "",
"ngl": -1, "ngl": -1,
"fit": true, "fit": true,
"reasoning": true "reasoning": false
},
"Qwen35-35B-A3B-Q6K-turbo4-256k": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.6,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 256000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.5-35B-A3B-Q6_K.gguf",
"chatTemplateKwargs": "{\"enable_thinking\": true}",
"ngl": 999,
"fit": true,
"reasoning": true
},
"Qwen35-35B-A3B-Q6K-Q8-256k": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.6,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 256000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.5-35B-A3B-Q6_K.gguf",
"chatTemplateKwargs": "",
"ngl": 999,
"fit": true,
"reasoning": true
}, },
"gemma-4-31B-it-UD-Q6KXL-54k": { "gemma-4-31B-it-UD-Q6KXL-54k": {
"host": "0.0.0.0", "host": "0.0.0.0",
@ -350,5 +240,71 @@
"ngl": 99, "ngl": 99,
"fit": false, "fit": false,
"reasoning": true "reasoning": true
},
"Exaone4": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 2048,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.9,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 131072,
"enableThinking": false,
"modelPath": "/home/kamma/models/EXAONE-4.0-32B-GGUF-Q6_K.gguf",
"chatTemplateKwargs": "",
"ngl": 99,
"fit": false,
"reasoning": true
},
"Qwen3.6-35B-A3B-UD-Q6_K_XL-FIT": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 4096,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.9,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 180000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.6-35B-A3B-UD-Q6_K_XL.gguf",
"chatTemplateKwargs": "",
"ngl": 99,
"fit": false,
"reasoning": true
},
"Qwen3.6-35B-A3B-UD-Q5_K_XL-FULL": {
"host": "0.0.0.0",
"port": 3080,
"parallel": 1,
"batchSize": 4096,
"threads": 99,
"flashAttention": true,
"kvUnified": true,
"cacheTypeK": "q8_0",
"cacheTypeV": "q8_0",
"temperature": 0.9,
"topP": 0.95,
"topK": 20,
"minP": 0.0,
"ctxSize": 180000,
"enableThinking": false,
"modelPath": "/home/kamma/models/Qwen3.6-35B-A3B-UD-Q5_K_XL.gguf",
"chatTemplateKwargs": "",
"ngl": 99,
"fit": false,
"reasoning": true
} }
} }

View File

@ -19,6 +19,7 @@ public class AppConfig {
private int windowHeight; private int windowHeight;
private int windowX; private int windowX;
private int windowY; private int windowY;
private String lastProfile;
private final ConfigLocation configLocation; private final ConfigLocation configLocation;
public AppConfig() { public AppConfig() {
@ -47,6 +48,7 @@ public class AppConfig {
windowHeight = Integer.parseInt(props.getProperty("windowHeight", String.valueOf(DEFAULT_HEIGHT))); windowHeight = Integer.parseInt(props.getProperty("windowHeight", String.valueOf(DEFAULT_HEIGHT)));
windowX = Integer.parseInt(props.getProperty("windowX", String.valueOf(DEFAULT_X))); windowX = Integer.parseInt(props.getProperty("windowX", String.valueOf(DEFAULT_X)));
windowY = Integer.parseInt(props.getProperty("windowY", String.valueOf(DEFAULT_Y))); windowY = Integer.parseInt(props.getProperty("windowY", String.valueOf(DEFAULT_Y)));
lastProfile = props.getProperty("lastProfile", "");
} catch (IOException | NumberFormatException e) { } catch (IOException | NumberFormatException e) {
// Use default values on error // Use default values on error
} }
@ -60,6 +62,9 @@ public class AppConfig {
props.setProperty("windowHeight", String.valueOf(windowHeight)); props.setProperty("windowHeight", String.valueOf(windowHeight));
props.setProperty("windowX", String.valueOf(windowX)); props.setProperty("windowX", String.valueOf(windowX));
props.setProperty("windowY", String.valueOf(windowY)); props.setProperty("windowY", String.valueOf(windowY));
if (lastProfile != null) {
props.setProperty("lastProfile", lastProfile);
}
try (FileOutputStream fos = new FileOutputStream(configLocation.getConfigPropertiesFile())) { try (FileOutputStream fos = new FileOutputStream(configLocation.getConfigPropertiesFile())) {
props.store(fos, "Llama Runner Configuration"); props.store(fos, "Llama Runner Configuration");
@ -99,4 +104,12 @@ public class AppConfig {
public void setWindowY(int windowY) { public void setWindowY(int windowY) {
this.windowY = windowY; this.windowY = windowY;
} }
public String getLastProfile() {
return lastProfile;
}
public void setLastProfile(String lastProfile) {
this.lastProfile = lastProfile;
}
} }

View File

@ -13,6 +13,8 @@ import java.awt.Toolkit;
import java.awt.Image; import java.awt.Image;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.StringSelection;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.File; import java.io.File;
@ -130,6 +132,10 @@ public class Main extends JFrame {
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
String profile = (String) profileComboBox.getSelectedItem();
if (profile != null) {
appConfig.setLastProfile(profile);
}
saveWindowConfig(); saveWindowConfig();
dispose(); dispose();
System.exit(0); System.exit(0);
@ -140,8 +146,12 @@ public class Main extends JFrame {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
loadModels(); loadModels();
loadProfiles(); loadProfiles();
if (profileComboBox.getItemCount() > 0) { if (appConfig.getLastProfile() != null && !appConfig.getLastProfile().isEmpty()) {
profileComboBox.setSelectedItem(appConfig.getLastProfile());
} else if (profileComboBox.getItemCount() > 0) {
profileComboBox.setSelectedIndex(0); profileComboBox.setSelectedIndex(0);
}
if (profileComboBox.getSelectedItem() != null) {
showLoadProfileDialog(); showLoadProfileDialog();
} }
updateCommandPreview(); updateCommandPreview();
@ -291,16 +301,23 @@ public class Main extends JFrame {
} }
private void loadProfiles() { private void loadProfiles() {
String selectedItem = (String) profileComboBox.getSelectedItem();
// Remove listener temporarily to prevent triggering during load // Remove listener temporarily to prevent triggering during load
profileComboBox.removeActionListener(profileChangeListener); profileComboBox.removeActionListener(profileChangeListener);
try { try {
profileComboBox.removeAllItems();
List<String> profiles = profileManager.listProfiles(); List<String> profiles = profileManager.listProfiles();
profiles.sort(String::compareToIgnoreCase); profiles.sort(String::compareToIgnoreCase);
for (String name : profiles) { for (String name : profiles) {
profileComboBox.addItem(name); profileComboBox.addItem(name);
} }
if (selectedItem != null) {
profileComboBox.setSelectedItem(selectedItem);
}
// Re-add listener after loading // Re-add listener after loading
profileComboBox.addActionListener(profileChangeListener); profileComboBox.addActionListener(profileChangeListener);
} catch (Exception e) { } catch (Exception e) {
@ -318,6 +335,7 @@ public class Main extends JFrame {
} }
String selectedItem = (String) profileComboBox.getSelectedItem(); String selectedItem = (String) profileComboBox.getSelectedItem();
if (selectedItem != null && !selectedItem.isEmpty()) { if (selectedItem != null && !selectedItem.isEmpty()) {
appConfig.setLastProfile(selectedItem);
showLoadProfileDialog(); showLoadProfileDialog();
} }
} }
@ -349,6 +367,7 @@ public class Main extends JFrame {
return; return;
} }
saveProfileToName(currentProfile); saveProfileToName(currentProfile);
loadProfiles();
JOptionPane.showMessageDialog(this, "Profile saved!"); JOptionPane.showMessageDialog(this, "Profile saved!");
} catch (IOException e) { } catch (IOException e) {
@ -641,7 +660,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
hostField = new JTextField("0.0.0.0", 15); hostField = new JTextField("0.0.0.0", 15);
hostField.setCaretColor(Color.WHITE); hostField.setCaretColor(Color.WHITE);
hostField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(hostField);
panel.add(hostField, gbc); panel.add(hostField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -653,7 +672,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
portField = new JTextField("3080", 10); portField = new JTextField("3080", 10);
portField.setCaretColor(Color.WHITE); portField.setCaretColor(Color.WHITE);
portField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(portField);
panel.add(portField, gbc); panel.add(portField, gbc);
return panel; return panel;
@ -677,7 +696,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
parallelField = new JTextField("1", 10); parallelField = new JTextField("1", 10);
parallelField.setCaretColor(Color.WHITE); parallelField.setCaretColor(Color.WHITE);
parallelField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(parallelField);
panel.add(parallelField, gbc); panel.add(parallelField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -689,7 +708,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
batchSizeField = new JTextField("4096", 10); batchSizeField = new JTextField("4096", 10);
batchSizeField.setCaretColor(Color.WHITE); batchSizeField.setCaretColor(Color.WHITE);
batchSizeField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(batchSizeField);
panel.add(batchSizeField, gbc); panel.add(batchSizeField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -701,7 +720,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
threadsField = new JTextField("99", 10); threadsField = new JTextField("99", 10);
threadsField.setCaretColor(Color.WHITE); threadsField.setCaretColor(Color.WHITE);
threadsField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(threadsField);
panel.add(threadsField, gbc); panel.add(threadsField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -769,7 +788,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
nglField = new JTextField("-1", 10); nglField = new JTextField("-1", 10);
nglField.setCaretColor(Color.WHITE); nglField.setCaretColor(Color.WHITE);
nglField.getDocument().addDocumentListener(createNglDocumentListener()); addFocusUpdateListener(nglField);
panel.add(nglField, gbc); panel.add(nglField, gbc);
// Fit parameter // Fit parameter
@ -816,7 +835,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
tempField = new JTextField("0.6", 10); tempField = new JTextField("0.6", 10);
tempField.setCaretColor(Color.WHITE); tempField.setCaretColor(Color.WHITE);
tempField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(tempField);
panel.add(tempField, gbc); panel.add(tempField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -828,7 +847,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
topPField = new JTextField("0.95", 10); topPField = new JTextField("0.95", 10);
topPField.setCaretColor(Color.WHITE); topPField.setCaretColor(Color.WHITE);
topPField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(topPField);
panel.add(topPField, gbc); panel.add(topPField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -840,7 +859,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
topKField = new JTextField("20", 10); topKField = new JTextField("20", 10);
topKField.setCaretColor(Color.WHITE); topKField.setCaretColor(Color.WHITE);
topKField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(topKField);
panel.add(topKField, gbc); panel.add(topKField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -852,7 +871,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
minPField = new JTextField("0.00", 10); minPField = new JTextField("0.00", 10);
minPField.setCaretColor(Color.WHITE); minPField.setCaretColor(Color.WHITE);
minPField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(minPField);
panel.add(minPField, gbc); panel.add(minPField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -864,8 +883,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
ctxSizeField = new JTextField("180000", 10); ctxSizeField = new JTextField("180000", 10);
ctxSizeField.setCaretColor(Color.WHITE); ctxSizeField.setCaretColor(Color.WHITE);
ctxSizeField.addActionListener(e -> updateCommandPreview()); addFocusUpdateListener(ctxSizeField);
ctxSizeField.getDocument().addDocumentListener(new PreviewUpdateListener(this::updateCommandPreview));
panel.add(ctxSizeField, gbc); panel.add(ctxSizeField, gbc);
gbc.gridx = 0; gbc.gridx = 0;
@ -878,7 +896,7 @@ public class Main extends JFrame {
gbc.weightx = 1.0; gbc.weightx = 1.0;
kwargsField = new JTextField("{\"enable_thinking\": true}"); kwargsField = new JTextField("{\"enable_thinking\": true}");
kwargsField.setCaretColor(Color.WHITE); kwargsField.setCaretColor(Color.WHITE);
kwargsField.getDocument().addDocumentListener(new PreviewUpdateListener(this::updateCommandPreview)); addFocusUpdateListener(kwargsField);
panel.add(kwargsField, gbc); panel.add(kwargsField, gbc);
return panel; return panel;
@ -924,8 +942,18 @@ public class Main extends JFrame {
if (isProfileLoading) { if (isProfileLoading) {
return; return;
} }
try {
String error = validateCurrentConfig();
if (error != null) {
JOptionPane.showMessageDialog(this, error, "Validation Error", JOptionPane.ERROR_MESSAGE);
return;
}
String command = buildCommand(); String command = buildCommand();
commandPreviewArea.setText(command); commandPreviewArea.setText(command);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Please enter valid numeric values.", "Validation Error",
JOptionPane.ERROR_MESSAGE);
}
} }
private void setNglFieldText(String text) { private void setNglFieldText(String text) {
@ -933,8 +961,13 @@ public class Main extends JFrame {
updateCommandPreview(); updateCommandPreview();
} }
private javax.swing.event.DocumentListener createNglDocumentListener() { private void addFocusUpdateListener(JTextField field) {
return new PreviewUpdateListener(this::updateCommandPreview); field.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
updateCommandPreview();
}
});
} }
private void copyCommandToClipboard() { private void copyCommandToClipboard() {