Enhance model management: add temperature, top-p, top-k, and min-p settings with UI sliders
This commit is contained in:
79
README.md
79
README.md
@@ -1,20 +1,73 @@
|
||||
# lm-launcher
|
||||
|
||||
**Program Name:** Machine Learning Model and Application Manager
|
||||
A small Swing GUI for managing local GGUF models and launching apps with model-dependent command-line placeholders.
|
||||
|
||||
**Purpose:** The program is a graphical user interface (GUI) application that allows users to manage machine learning models and applications. It provides a user-friendly interface for adding, editing, deleting, and cloning models and applications, as well as running applications with selected models.
|
||||
## What it does
|
||||
|
||||
**Key Features:**
|
||||
- scans a configured models directory for `.gguf` files
|
||||
- stores per-model settings in `models.json`
|
||||
- stores app launch definitions in `apps.json`
|
||||
- launches apps with placeholders resolved from the selected model
|
||||
|
||||
1. **Model Management:** Users can add, edit, delete, and clone models, as well as view their properties.
|
||||
2. **Application Management:** Users can add, edit, delete, and clone applications, as well as view their properties and run them with a selected model.
|
||||
3. **Data Storage:** The program uses a data storage system that loads and manages data from two JSON files: "models.json" and "apps.json".
|
||||
4. **GUI Components:** The program uses various GUI components, such as buttons, labels, sliders, and tables, to provide a user-friendly interface.
|
||||
5. **Event Handling:** The program uses event listeners to handle user interactions, such as button clicks and table selections.
|
||||
6. **Data Refresh:** The program has a method called `refresh()` that updates the GUI components with the latest data from the data storage.
|
||||
7. **Model and Application Editing:** Users can edit the properties of models and applications using dedicated dialog windows.
|
||||
8. **Argument Management:** Users can add, edit, or remove rows in a table to manage application arguments, and the changes are reflected in the application's arguments.
|
||||
## Model settings
|
||||
|
||||
**Overall:** The program provides a comprehensive GUI application for managing machine learning models and applications, making it easier for users to work with these components and run applications with selected models.
|
||||
Each model can store:
|
||||
|
||||
*[requests=10, requestDuration=PT25.84142404S, inTokens=10623, outTokens=1240, tps=49.6]*
|
||||
- context length
|
||||
- max context length
|
||||
- threads
|
||||
- GPU layers
|
||||
- prompt template
|
||||
- temperature
|
||||
- top-p
|
||||
- top-k
|
||||
- min-p
|
||||
|
||||
The main window also provides sliders for quickly adjusting launch-time values for:
|
||||
|
||||
- context length
|
||||
- threads
|
||||
- GPU layers
|
||||
- temperature
|
||||
- top-p
|
||||
- top-k
|
||||
- min-p
|
||||
|
||||
## App placeholders
|
||||
|
||||
Use these tokens in app arguments:
|
||||
|
||||
- `MODEL`
|
||||
- `CONTEXT_SIZE`
|
||||
- `THREADS`
|
||||
- `GPU_LAYERS`
|
||||
- `TEMP`
|
||||
- `TOP_P`
|
||||
- `TOP_K`
|
||||
- `MIN_P`
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
-m MODEL -c CONTEXT_SIZE -t THREADS -ngl GPU_LAYERS --temp TEMP --top-p TOP_P --top-k TOP_K --min-p MIN_P
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
- `lm-launcher.properties` – launcher configuration
|
||||
- `models.json` – saved model settings
|
||||
- `apps.json` – saved app definitions
|
||||
- `run.sh` – starts the packaged launcher jar
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
./run.sh
|
||||
```
|
||||
|
||||
To build from source with the bundled Jackson jars:
|
||||
|
||||
```bash
|
||||
javac -cp jackson-annotations-2.17.2.jar:jackson-core-2.17.2.jar:jackson-databind-2.17.2.jar -d /tmp/lm-launcher-build $(find src -name '*.java' | sort)
|
||||
java -cp /tmp/lm-launcher-build:jackson-annotations-2.17.2.jar:jackson-core-2.17.2.jar:jackson-databind-2.17.2.jar de.extio.lm_launcher.Main
|
||||
```
|
||||
@@ -1 +1 @@
|
||||
{"apps":[{"path":"file:///home/sb/lm/koboldcpp-rocm/koboldcpp.py","interpreter":"file:///usr/bin/python","arguments":[],"appArguments":[{"argument":"--usecublas","optional":true,"default_":true},{"argument":"mmq","optional":true,"default_":false},{"argument":"lowvram","optional":true,"default_":false},{"argument":"0","optional":true,"default_":true},{"argument":"--gpulayers","optional":true,"default_":true},{"argument":"GPU_LAYERS","optional":true,"default_":true},{"argument":"--smartcontext","optional":true,"default_":false},{"argument":"--noshift","optional":true,"default_":false},{"argument":"--contextsize","optional":false,"default_":true},{"argument":"CONTEXT_SIZE","optional":false,"default_":true},{"argument":"--launch","optional":false,"default_":true},{"argument":"--host","optional":true,"default_":false},{"argument":"0.0.0.0","optional":true,"default_":false},{"argument":"--threads","optional":false,"default_":true},{"argument":"THREADS","optional":false,"default_":true},{"argument":"--model","optional":false,"default_":true},{"argument":"MODEL","optional":false,"default_":true}]},{"path":"file:///home/sb/lm/llama.cpp/llama-server","interpreter":null,"arguments":[],"appArguments":[{"argument":"-nkvo","optional":true,"default_":false},{"argument":"--parallel","optional":true,"default_":false},{"argument":"2","optional":true,"default_":false},{"argument":"4","optional":true,"default_":false},{"argument":"--host","optional":true,"default_":true},{"argument":"0.0.0.0","optional":true,"default_":true},{"argument":"--port","optional":false,"default_":true},{"argument":"5001","optional":false,"default_":true},{"argument":"-t","optional":false,"default_":true},{"argument":"THREADS","optional":false,"default_":true},{"argument":"-ngl","optional":false,"default_":true},{"argument":"GPU_LAYERS","optional":false,"default_":true},{"argument":"--ctx-size","optional":false,"default_":true},{"argument":"CONTEXT_SIZE","optional":false,"default_":true},{"argument":"-m","optional":false,"default_":true},{"argument":"MODEL","optional":false,"default_":true}]},{"path":"file:///home/sb/lm/SillyTavern/start.sh","interpreter":null,"arguments":[],"appArguments":[]}]}
|
||||
{"apps":[{"path":"file:///home/sb/lm/koboldcpp-rocm/koboldcpp.py","interpreter":"file:///usr/bin/python","arguments":[],"appArguments":[{"argument":"--usecublas","optional":true,"default_":true},{"argument":"mmq","optional":true,"default_":false},{"argument":"lowvram","optional":true,"default_":false},{"argument":"0","optional":true,"default_":true},{"argument":"--gpulayers","optional":true,"default_":true},{"argument":"GPU_LAYERS","optional":true,"default_":true},{"argument":"--smartcontext","optional":true,"default_":false},{"argument":"--noshift","optional":true,"default_":false},{"argument":"--contextsize","optional":false,"default_":true},{"argument":"CONTEXT_SIZE","optional":false,"default_":true},{"argument":"--launch","optional":false,"default_":true},{"argument":"--host","optional":true,"default_":false},{"argument":"0.0.0.0","optional":true,"default_":false},{"argument":"--threads","optional":false,"default_":true},{"argument":"THREADS","optional":false,"default_":true},{"argument":"--model","optional":false,"default_":true},{"argument":"MODEL","optional":false,"default_":true}]},{"path":"file:///home/sb/lm/llama.cpp/llama-server","interpreter":null,"arguments":[],"appArguments":[{"argument":"-nkvo","optional":true,"default_":false},{"argument":"--parallel","optional":true,"default_":false},{"argument":"2","optional":true,"default_":false},{"argument":"4","optional":true,"default_":false},{"argument":"--host","optional":true,"default_":true},{"argument":"0.0.0.0","optional":true,"default_":true},{"argument":"--port","optional":false,"default_":true},{"argument":"5001","optional":false,"default_":true},{"argument":"-t","optional":false,"default_":true},{"argument":"THREADS","optional":false,"default_":true},{"argument":"-ngl","optional":false,"default_":true},{"argument":"GPU_LAYERS","optional":false,"default_":true},{"argument":"--ctx-size","optional":false,"default_":true},{"argument":"CONTEXT_SIZE","optional":false,"default_":true},{"argument":"-m","optional":false,"default_":true},{"argument":"MODEL","optional":false,"default_":true}]},{"path":"file:///home/sb/lm/SillyTavern/start.sh","interpreter":null,"arguments":[],"appArguments":[]},{"path":"file:///home/sb/lm/ollama-oai-bridge/start.sh","interpreter":null,"arguments":[],"appArguments":[]}]}
|
||||
BIN
lm-launcher.jar
BIN
lm-launcher.jar
Binary file not shown.
@@ -15,7 +15,11 @@ record App(Path path, Path interpreter, @Deprecated List<String> arguments, List
|
||||
"MODEL", m -> m.path(),
|
||||
"CONTEXT_SIZE", m -> String.valueOf(m.contextSize()),
|
||||
"THREADS", m -> String.valueOf(m.threads()),
|
||||
"GPU_LAYERS", m -> String.valueOf(m.gpuLayers()));
|
||||
"GPU_LAYERS", m -> String.valueOf(m.gpuLayers()),
|
||||
"TEMP", Model::temperatureDisplay,
|
||||
"TOP_P", Model::topPDisplay,
|
||||
"TOP_K", Model::topKDisplay,
|
||||
"MIN_P", Model::minPDisplay);
|
||||
|
||||
String argumentsToString(boolean showAll) {
|
||||
return this.argumentsToStringByArgs(this.appArguments.stream(), showAll);
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.nio.file.attribute.FileTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -46,8 +45,10 @@ public class Data {
|
||||
// Migration
|
||||
for (int i = 0; i < modelData.models().size(); i++) {
|
||||
final Model model = modelData.models.get(i);
|
||||
if (model.maxContextSize() < model.contextSize() || model.promptTemplate() == null) {
|
||||
modelData.models.set(i, new Model(model.path(), model.contextSize(), model.contextSize(), model.gpuLayers(), model.threads(), Objects.requireNonNullElse(model.promptTemplate(), ""), model.ctime()));
|
||||
if (model.maxContextSize() < model.contextSize() || model.promptTemplate() == null || model.temperature() == null || model.topP() == null || model.topK() == null
|
||||
|| model.minP() == null) {
|
||||
modelData.models.set(i, new Model(model.path(), model.contextSize(), model.maxContextSize(), model.gpuLayers(), model.threads(), model.temperature(), model.topP(), model.topK(),
|
||||
model.minP(), model.promptTemplate(), model.ctime()));
|
||||
}
|
||||
}
|
||||
sortModels();
|
||||
@@ -154,7 +155,7 @@ public class Data {
|
||||
catch (final IOException e) {
|
||||
// Use 0 as fallback
|
||||
}
|
||||
return new Model(path, 16000, 128000, 99, 6, "", ctime);
|
||||
return new Model(path, 16000, 128000, 99, 6, Model.DEFAULT_TEMPERATURE, Model.DEFAULT_TOP_P, Model.DEFAULT_TOP_K, Model.DEFAULT_MIN_P, "", ctime);
|
||||
}
|
||||
|
||||
static record ModelData(List<Model> models) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -32,6 +33,7 @@ import javax.swing.JSplitPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.WindowConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
@@ -48,6 +50,8 @@ public class LaunchFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int DECIMAL_SLIDER_SCALE = 100;
|
||||
|
||||
private final JPanel contentPane;
|
||||
|
||||
JPanel panel;
|
||||
@@ -125,6 +129,30 @@ public class LaunchFrame extends JFrame {
|
||||
|
||||
JLabel lblPromptTemplate_1;
|
||||
|
||||
JLabel lblTemperature;
|
||||
|
||||
JSlider slider_temperature;
|
||||
|
||||
JLabel lblTemperatureValue;
|
||||
|
||||
JLabel lblTopP;
|
||||
|
||||
JSlider slider_topP;
|
||||
|
||||
JLabel lblTopPValue;
|
||||
|
||||
JLabel lblTopK;
|
||||
|
||||
JSlider slider_topK;
|
||||
|
||||
JLabel lblTopKValue;
|
||||
|
||||
JLabel lblMinP;
|
||||
|
||||
JSlider slider_minP;
|
||||
|
||||
JLabel lblMinPValue;
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
@@ -255,8 +283,12 @@ public class LaunchFrame extends JFrame {
|
||||
this.scrollPane_1.setViewportView(this.modelTree);
|
||||
|
||||
{
|
||||
final JScrollPane modelSettingsScrollPane = new JScrollPane();
|
||||
modelSettingsScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
modelSettingsScrollPane.getVerticalScrollBar().setUnitIncrement(UIScaler.scale(16));
|
||||
this.splitPane_2.setRightComponent(modelSettingsScrollPane);
|
||||
this.panel_3 = new JPanel();
|
||||
this.splitPane_2.setRightComponent(this.panel_3);
|
||||
modelSettingsScrollPane.setViewportView(this.panel_3);
|
||||
this.panel_3.setLayout(new GridLayout(0, 1, 0, 0));
|
||||
{
|
||||
this.lblContextLength = new JLabel("Context Length");
|
||||
@@ -306,6 +338,7 @@ public class LaunchFrame extends JFrame {
|
||||
}
|
||||
{
|
||||
this.lblPromptTemplate = new JLabel("Prompt Template");
|
||||
this.lblPromptTemplate.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblPromptTemplate);
|
||||
}
|
||||
{
|
||||
@@ -313,6 +346,98 @@ public class LaunchFrame extends JFrame {
|
||||
this.lblPromptTemplate_1.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblPromptTemplate_1);
|
||||
}
|
||||
{
|
||||
this.lblTemperature = new JLabel("Temperature");
|
||||
this.lblTemperature.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTemperature);
|
||||
}
|
||||
{
|
||||
this.slider_temperature = new JSlider();
|
||||
this.slider_temperature.setMinimum((int) (Model.MIN_TEMPERATURE * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_temperature.setMaximum((int) (Model.MAX_TEMPERATURE * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_temperature.setValue(LaunchFrame.doubleToSlider(Model.DEFAULT_TEMPERATURE));
|
||||
this.slider_temperature.setMajorTickSpacing(50);
|
||||
this.slider_temperature.setMinorTickSpacing(5);
|
||||
this.slider_temperature.setLabelTable(LaunchFrame.createDecimalLabelTable(new int[] { 0, 50, 100, 150, 200 }));
|
||||
this.slider_temperature.setPaintLabels(true);
|
||||
this.slider_temperature.setPaintTicks(true);
|
||||
this.slider_temperature.addChangeListener(e -> LaunchFrame.this.updateSamplingValueLabels());
|
||||
this.panel_3.add(this.slider_temperature);
|
||||
}
|
||||
{
|
||||
this.lblTemperatureValue = new JLabel("-");
|
||||
this.lblTemperatureValue.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTemperatureValue);
|
||||
}
|
||||
{
|
||||
this.lblTopP = new JLabel("Top P");
|
||||
this.lblTopP.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTopP);
|
||||
}
|
||||
{
|
||||
this.slider_topP = new JSlider();
|
||||
this.slider_topP.setMinimum((int) (Model.MIN_TOP_P * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_topP.setMaximum((int) (Model.MAX_TOP_P * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_topP.setValue(LaunchFrame.doubleToSlider(Model.DEFAULT_TOP_P));
|
||||
this.slider_topP.setMajorTickSpacing(25);
|
||||
this.slider_topP.setMinorTickSpacing(5);
|
||||
this.slider_topP.setLabelTable(LaunchFrame.createDecimalLabelTable(new int[] { 0, 25, 50, 75, 100 }));
|
||||
this.slider_topP.setPaintLabels(true);
|
||||
this.slider_topP.setPaintTicks(true);
|
||||
this.slider_topP.addChangeListener(e -> LaunchFrame.this.updateSamplingValueLabels());
|
||||
this.panel_3.add(this.slider_topP);
|
||||
}
|
||||
{
|
||||
this.lblTopPValue = new JLabel("-");
|
||||
this.lblTopPValue.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTopPValue);
|
||||
}
|
||||
{
|
||||
this.lblTopK = new JLabel("Top K");
|
||||
this.lblTopK.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTopK);
|
||||
}
|
||||
{
|
||||
this.slider_topK = new JSlider();
|
||||
this.slider_topK.setMinimum(Model.MIN_TOP_K);
|
||||
this.slider_topK.setMaximum(Model.MAX_TOP_K);
|
||||
this.slider_topK.setValue(Model.DEFAULT_TOP_K);
|
||||
this.slider_topK.setMajorTickSpacing(100);
|
||||
this.slider_topK.setMinorTickSpacing(25);
|
||||
this.slider_topK.setSnapToTicks(true);
|
||||
this.slider_topK.setPaintLabels(true);
|
||||
this.slider_topK.setPaintTicks(true);
|
||||
this.slider_topK.addChangeListener(e -> LaunchFrame.this.updateSamplingValueLabels());
|
||||
this.panel_3.add(this.slider_topK);
|
||||
}
|
||||
{
|
||||
this.lblTopKValue = new JLabel("-");
|
||||
this.lblTopKValue.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblTopKValue);
|
||||
}
|
||||
{
|
||||
this.lblMinP = new JLabel("Min P");
|
||||
this.lblMinP.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblMinP);
|
||||
}
|
||||
{
|
||||
this.slider_minP = new JSlider();
|
||||
this.slider_minP.setMinimum((int) (Model.MIN_MIN_P * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_minP.setMaximum((int) (Model.MAX_MIN_P * DECIMAL_SLIDER_SCALE));
|
||||
this.slider_minP.setValue(LaunchFrame.doubleToSlider(Model.DEFAULT_MIN_P));
|
||||
this.slider_minP.setMajorTickSpacing(25);
|
||||
this.slider_minP.setMinorTickSpacing(5);
|
||||
this.slider_minP.setLabelTable(LaunchFrame.createDecimalLabelTable(new int[] { 0, 25, 50, 75, 100 }));
|
||||
this.slider_minP.setPaintLabels(true);
|
||||
this.slider_minP.setPaintTicks(true);
|
||||
this.slider_minP.addChangeListener(e -> LaunchFrame.this.updateSamplingValueLabels());
|
||||
this.panel_3.add(this.slider_minP);
|
||||
}
|
||||
{
|
||||
this.lblMinPValue = new JLabel("-");
|
||||
this.lblMinPValue.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.panel_3.add(this.lblMinPValue);
|
||||
}
|
||||
{
|
||||
this.verticalStrut = Box.createVerticalStrut(20);
|
||||
this.panel_3.add(this.verticalStrut);
|
||||
@@ -448,6 +573,10 @@ public class LaunchFrame extends JFrame {
|
||||
template.maxContextSize(),
|
||||
LaunchFrame.this.slider_gpu.getValue(),
|
||||
LaunchFrame.this.slider_threads.getValue(),
|
||||
LaunchFrame.this.sliderValue(LaunchFrame.this.slider_temperature),
|
||||
LaunchFrame.this.sliderValue(LaunchFrame.this.slider_topP),
|
||||
LaunchFrame.this.slider_topK.getValue(),
|
||||
LaunchFrame.this.sliderValue(LaunchFrame.this.slider_minP),
|
||||
template.promptTemplate(),
|
||||
template.ctime());
|
||||
}
|
||||
@@ -484,6 +613,7 @@ public class LaunchFrame extends JFrame {
|
||||
UIScaler.scaleComponentFonts(this);
|
||||
|
||||
UIScaler.centerOnPrimaryDisplay(this);
|
||||
this.updateSamplingValueLabels();
|
||||
this.repaint();
|
||||
this.splitPane.setDividerLocation(0.33);
|
||||
this.splitPane_1.setDividerLocation(0.66);
|
||||
@@ -512,7 +642,35 @@ public class LaunchFrame extends JFrame {
|
||||
|
||||
this.slider_threads.setValue(model.threads());
|
||||
this.slider_gpu.setValue(model.gpuLayers());
|
||||
this.slider_temperature.setValue(LaunchFrame.doubleToSlider(model.temperatureValue()));
|
||||
this.slider_topP.setValue(LaunchFrame.doubleToSlider(model.topPValue()));
|
||||
this.slider_topK.setValue(model.topKValue());
|
||||
this.slider_minP.setValue(LaunchFrame.doubleToSlider(model.minPValue()));
|
||||
this.lblPromptTemplate_1.setText(model.promptTemplate() != null && !model.promptTemplate().isEmpty() ? model.promptTemplate() : "-");
|
||||
this.updateSamplingValueLabels();
|
||||
}
|
||||
|
||||
private void updateSamplingValueLabels() {
|
||||
this.lblTemperatureValue.setText(Model.formatDecimal(this.sliderValue(this.slider_temperature)));
|
||||
this.lblTopPValue.setText(Model.formatDecimal(this.sliderValue(this.slider_topP)));
|
||||
this.lblTopKValue.setText(String.valueOf(this.slider_topK.getValue()));
|
||||
this.lblMinPValue.setText(Model.formatDecimal(this.sliderValue(this.slider_minP)));
|
||||
}
|
||||
|
||||
private double sliderValue(final JSlider slider) {
|
||||
return slider.getValue() / (double) DECIMAL_SLIDER_SCALE;
|
||||
}
|
||||
|
||||
private static int doubleToSlider(final double value) {
|
||||
return (int) Math.round(value * DECIMAL_SLIDER_SCALE);
|
||||
}
|
||||
|
||||
private static Hashtable<Integer, JLabel> createDecimalLabelTable(final int[] values) {
|
||||
final Hashtable<Integer, JLabel> labels = new Hashtable<>();
|
||||
for (final int value : values) {
|
||||
labels.put(value, new JLabel(Model.formatDecimal(value / (double) DECIMAL_SLIDER_SCALE)));
|
||||
}
|
||||
return labels;
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
|
||||
@@ -1,4 +1,97 @@
|
||||
package de.extio.lm_launcher;
|
||||
|
||||
record Model(String path, int contextSize, int maxContextSize, int gpuLayers, int threads, String promptTemplate, long ctime) {
|
||||
import java.math.BigDecimal;
|
||||
|
||||
record Model(String path, int contextSize, int maxContextSize, int gpuLayers, int threads, Double temperature, Double topP,
|
||||
Integer topK, Double minP, String promptTemplate, long ctime) {
|
||||
|
||||
static final double DEFAULT_TEMPERATURE = 0.8d;
|
||||
|
||||
static final double DEFAULT_TOP_P = 0.95d;
|
||||
|
||||
static final int DEFAULT_TOP_K = 40;
|
||||
|
||||
static final double DEFAULT_MIN_P = 0.05d;
|
||||
|
||||
static final double MIN_TEMPERATURE = 0d;
|
||||
|
||||
static final double MAX_TEMPERATURE = 2d;
|
||||
|
||||
static final double MIN_TOP_P = 0d;
|
||||
|
||||
static final double MAX_TOP_P = 1d;
|
||||
|
||||
static final int MIN_TOP_K = 0;
|
||||
|
||||
static final int MAX_TOP_K = 500;
|
||||
|
||||
static final double MIN_MIN_P = 0d;
|
||||
|
||||
static final double MAX_MIN_P = 1d;
|
||||
|
||||
public Model {
|
||||
maxContextSize = Math.max(Math.max(1, maxContextSize), Math.max(1, contextSize));
|
||||
contextSize = clampInt(contextSize, 1, maxContextSize);
|
||||
gpuLayers = Math.max(0, gpuLayers);
|
||||
threads = Math.max(0, threads);
|
||||
temperature = sanitizeDouble(temperature, DEFAULT_TEMPERATURE, MIN_TEMPERATURE, MAX_TEMPERATURE);
|
||||
topP = sanitizeDouble(topP, DEFAULT_TOP_P, MIN_TOP_P, MAX_TOP_P);
|
||||
topK = sanitizeInt(topK, DEFAULT_TOP_K, MIN_TOP_K, MAX_TOP_K);
|
||||
minP = sanitizeDouble(minP, DEFAULT_MIN_P, MIN_MIN_P, MAX_MIN_P);
|
||||
promptTemplate = promptTemplate == null ? "" : promptTemplate;
|
||||
}
|
||||
|
||||
double temperatureValue() {
|
||||
return this.temperature;
|
||||
}
|
||||
|
||||
double topPValue() {
|
||||
return this.topP;
|
||||
}
|
||||
|
||||
int topKValue() {
|
||||
return this.topK;
|
||||
}
|
||||
|
||||
double minPValue() {
|
||||
return this.minP;
|
||||
}
|
||||
|
||||
String temperatureDisplay() {
|
||||
return formatDecimal(this.temperatureValue());
|
||||
}
|
||||
|
||||
String topPDisplay() {
|
||||
return formatDecimal(this.topPValue());
|
||||
}
|
||||
|
||||
String topKDisplay() {
|
||||
return String.valueOf(this.topKValue());
|
||||
}
|
||||
|
||||
String minPDisplay() {
|
||||
return formatDecimal(this.minPValue());
|
||||
}
|
||||
|
||||
private static Double sanitizeDouble(final Double value, final double defaultValue, final double minValue, final double maxValue) {
|
||||
if (value == null || value.isNaN() || value.isInfinite()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Math.max(minValue, Math.min(maxValue, value));
|
||||
}
|
||||
|
||||
private static Integer sanitizeInt(final Integer value, final int defaultValue, final int minValue, final int maxValue) {
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return clampInt(value, minValue, maxValue);
|
||||
}
|
||||
|
||||
private static int clampInt(final int value, final int minValue, final int maxValue) {
|
||||
return Math.max(minValue, Math.min(maxValue, value));
|
||||
}
|
||||
|
||||
static String formatDecimal(final double value) {
|
||||
return BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.function.Consumer;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.WindowConstants;
|
||||
@@ -42,18 +43,27 @@ public class ModelPropertiesDialog extends JDialog {
|
||||
JTextField textField_3;
|
||||
JLabel lblPromptTemplate;
|
||||
JTextField txtPrompttemplate;
|
||||
JLabel lblTemperature;
|
||||
JTextField txtTemperature;
|
||||
JLabel lblTopP;
|
||||
JTextField txtTopP;
|
||||
JLabel lblTopK;
|
||||
JTextField txtTopK;
|
||||
JLabel lblMinP;
|
||||
JTextField txtMinP;
|
||||
|
||||
/**
|
||||
* Create the dialog.
|
||||
*/
|
||||
public ModelPropertiesDialog(final Frame parent, final String modelPath, final Model editModel, final Consumer<Model> modelConsumer) {
|
||||
super(parent);
|
||||
final Model modelToEdit = editModel != null ? editModel : Data.defaultModel(modelPath);
|
||||
this.setTitle("Model properties");
|
||||
this.setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
this.setModal(true);
|
||||
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
this.setBounds(UIScaler.scale(100), UIScaler.scale(100), UIScaler.scale(678), UIScaler.scale(191));
|
||||
this.setBounds(UIScaler.scale(100), UIScaler.scale(100), UIScaler.scale(678), UIScaler.scale(320));
|
||||
this.getContentPane().setLayout(new BorderLayout());
|
||||
this.contentPanel.setBorder(new EmptyBorder(UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5)));
|
||||
this.getContentPane().add(this.contentPanel, BorderLayout.CENTER);
|
||||
@@ -106,6 +116,46 @@ public class ModelPropertiesDialog extends JDialog {
|
||||
this.contentPanel.add(this.textField_1);
|
||||
this.textField_1.setColumns(10);
|
||||
}
|
||||
{
|
||||
this.lblTemperature = new JLabel("Temperature");
|
||||
this.contentPanel.add(this.lblTemperature);
|
||||
}
|
||||
{
|
||||
this.txtTemperature = new JTextField();
|
||||
this.txtTemperature.setText(Model.formatDecimal(Model.DEFAULT_TEMPERATURE));
|
||||
this.contentPanel.add(this.txtTemperature);
|
||||
this.txtTemperature.setColumns(10);
|
||||
}
|
||||
{
|
||||
this.lblTopP = new JLabel("Top P");
|
||||
this.contentPanel.add(this.lblTopP);
|
||||
}
|
||||
{
|
||||
this.txtTopP = new JTextField();
|
||||
this.txtTopP.setText(Model.formatDecimal(Model.DEFAULT_TOP_P));
|
||||
this.contentPanel.add(this.txtTopP);
|
||||
this.txtTopP.setColumns(10);
|
||||
}
|
||||
{
|
||||
this.lblTopK = new JLabel("Top K");
|
||||
this.contentPanel.add(this.lblTopK);
|
||||
}
|
||||
{
|
||||
this.txtTopK = new JTextField();
|
||||
this.txtTopK.setText(String.valueOf(Model.DEFAULT_TOP_K));
|
||||
this.contentPanel.add(this.txtTopK);
|
||||
this.txtTopK.setColumns(10);
|
||||
}
|
||||
{
|
||||
this.lblMinP = new JLabel("Min P");
|
||||
this.contentPanel.add(this.lblMinP);
|
||||
}
|
||||
{
|
||||
this.txtMinP = new JTextField();
|
||||
this.txtMinP.setText(Model.formatDecimal(Model.DEFAULT_MIN_P));
|
||||
this.contentPanel.add(this.txtMinP);
|
||||
this.txtMinP.setColumns(10);
|
||||
}
|
||||
{
|
||||
final JPanel buttonPane = new JPanel();
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
@@ -116,18 +166,31 @@ public class ModelPropertiesDialog extends JDialog {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
try {
|
||||
final int contextSize = ModelPropertiesDialog.clampInt(ModelPropertiesDialog.parseIntField(ModelPropertiesDialog.this.textField_3, "Context Length"), 1,
|
||||
Integer.MAX_VALUE);
|
||||
final int maxContextSize = ModelPropertiesDialog.clampInt(ModelPropertiesDialog.parseIntField(ModelPropertiesDialog.this.textField, "Max Context Length"), 1,
|
||||
Integer.MAX_VALUE);
|
||||
final int gpuLayers = Math.max(0, ModelPropertiesDialog.parseIntField(ModelPropertiesDialog.this.textField_1, "GPU Layers"));
|
||||
final int threads = Math.max(0, ModelPropertiesDialog.parseIntField(ModelPropertiesDialog.this.textField_2, "Threads"));
|
||||
final double temperature = ModelPropertiesDialog.clampDouble(ModelPropertiesDialog.parseDoubleField(ModelPropertiesDialog.this.txtTemperature, "Temperature"),
|
||||
Model.MIN_TEMPERATURE, Model.MAX_TEMPERATURE);
|
||||
final double topP = ModelPropertiesDialog.clampDouble(ModelPropertiesDialog.parseDoubleField(ModelPropertiesDialog.this.txtTopP, "Top P"), Model.MIN_TOP_P,
|
||||
Model.MAX_TOP_P);
|
||||
final int topK = ModelPropertiesDialog.clampInt(ModelPropertiesDialog.parseIntField(ModelPropertiesDialog.this.txtTopK, "Top K"), Model.MIN_TOP_K,
|
||||
Model.MAX_TOP_K);
|
||||
final double minP = ModelPropertiesDialog.clampDouble(ModelPropertiesDialog.parseDoubleField(ModelPropertiesDialog.this.txtMinP, "Min P"), Model.MIN_MIN_P,
|
||||
Model.MAX_MIN_P);
|
||||
ModelPropertiesDialog.this.setVisible(false);
|
||||
final Model modelToSave = editModel != null ? editModel : Data.defaultModel(modelPath);
|
||||
modelConsumer.accept(
|
||||
new Model(modelPath,
|
||||
Integer.parseInt(ModelPropertiesDialog.this.textField_3.getText()),
|
||||
Integer.parseInt(ModelPropertiesDialog.this.textField.getText()),
|
||||
Integer.parseInt(ModelPropertiesDialog.this.textField_1.getText()),
|
||||
Integer.parseInt(ModelPropertiesDialog.this.textField_2.getText()),
|
||||
ModelPropertiesDialog.this.txtPrompttemplate.getText(),
|
||||
modelToSave.ctime()));
|
||||
new Model(modelPath, contextSize, maxContextSize, gpuLayers, threads, temperature, topP, topK, minP, ModelPropertiesDialog.this.txtPrompttemplate.getText(),
|
||||
modelToEdit.ctime()));
|
||||
ModelPropertiesDialog.this.dispose();
|
||||
}
|
||||
catch (final NumberFormatException nfe) {
|
||||
JOptionPane.showMessageDialog(ModelPropertiesDialog.this, nfe.getMessage(), "Invalid model property", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
okButton.setActionCommand("OK");
|
||||
buttonPane.add(okButton);
|
||||
@@ -145,16 +208,44 @@ public class ModelPropertiesDialog extends JDialog {
|
||||
contentPanel.add(this.txtPrompttemplate);
|
||||
this.txtPrompttemplate.setColumns(10);
|
||||
}
|
||||
if (editModel != null) {
|
||||
this.textField.setText(String.valueOf(editModel.maxContextSize()));
|
||||
this.textField_1.setText(String.valueOf(editModel.gpuLayers()));
|
||||
this.textField_2.setText(String.valueOf(editModel.threads()));
|
||||
this.textField_3.setText(String.valueOf(editModel.contextSize()));
|
||||
this.txtPrompttemplate.setText(editModel.promptTemplate());
|
||||
}
|
||||
this.textField.setText(String.valueOf(modelToEdit.maxContextSize()));
|
||||
this.textField_1.setText(String.valueOf(modelToEdit.gpuLayers()));
|
||||
this.textField_2.setText(String.valueOf(modelToEdit.threads()));
|
||||
this.textField_3.setText(String.valueOf(modelToEdit.contextSize()));
|
||||
this.txtTemperature.setText(modelToEdit.temperatureDisplay());
|
||||
this.txtTopP.setText(modelToEdit.topPDisplay());
|
||||
this.txtTopK.setText(modelToEdit.topKDisplay());
|
||||
this.txtMinP.setText(modelToEdit.minPDisplay());
|
||||
this.txtPrompttemplate.setText(modelToEdit.promptTemplate());
|
||||
|
||||
// Apply font scaling to all components
|
||||
UIScaler.scaleComponentFonts(this);
|
||||
}
|
||||
|
||||
private static int parseIntField(final JTextField field, final String fieldName) {
|
||||
try {
|
||||
return Integer.parseInt(field.getText().trim());
|
||||
}
|
||||
catch (final NumberFormatException nfe) {
|
||||
throw new NumberFormatException(fieldName + " must be a whole number.");
|
||||
}
|
||||
}
|
||||
|
||||
private static double parseDoubleField(final JTextField field, final String fieldName) {
|
||||
try {
|
||||
return Double.parseDouble(field.getText().trim());
|
||||
}
|
||||
catch (final NumberFormatException nfe) {
|
||||
throw new NumberFormatException(fieldName + " must be a decimal number.");
|
||||
}
|
||||
}
|
||||
|
||||
private static int clampInt(final int value, final int minValue, final int maxValue) {
|
||||
return Math.max(minValue, Math.min(maxValue, value));
|
||||
}
|
||||
|
||||
private static double clampDouble(final double value, final double minValue, final double maxValue) {
|
||||
return Math.max(minValue, Math.min(maxValue, value));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user