From f05611ebb4bf1bafe6daf69ad38260055621b9bb Mon Sep 17 00:00:00 2001 From: extio-de Date: Fri, 29 May 2026 21:36:43 +0200 Subject: [PATCH] Enhance model management: add temperature, top-p, top-k, and min-p settings with UI sliders --- README.md | 79 +++++++-- apps.json | 2 +- lm-launcher.jar | Bin 2179656 -> 2185218 bytes src/de/extio/lm_launcher/App.java | 6 +- src/de/extio/lm_launcher/Data.java | 9 +- src/de/extio/lm_launcher/LaunchFrame.java | 160 +++++++++++++++++- src/de/extio/lm_launcher/Model.java | 95 ++++++++++- .../lm_launcher/ModelPropertiesDialog.java | 129 +++++++++++--- 8 files changed, 440 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 9c7fe24..55d0bd3 100644 --- a/README.md +++ b/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 +``` \ No newline at end of file diff --git a/apps.json b/apps.json index 7c3acac..2ca1a4c 100644 --- a/apps.json +++ b/apps.json @@ -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":[]}]} \ No newline at end of file diff --git a/lm-launcher.jar b/lm-launcher.jar index 0996152f4098c73d60927a0d86cc92568fc47308..8013ace71c7280f5ed0e01848ebe629636f7e69e 100644 GIT binary patch delta 38754 zcmZs>V~}M_v^82?w#_bgnO(MR?6TR_WovhtyKLJwyKLLGZGGpQ`(DKNZoG($7$ak@ z%pYrIwV*S;(R`CBwIpol{|A-4T2Eu0z-s}As4M+vS3=_d zke86+KQty}hVUrrjNe~k0$ylY8R{$~enyeM(cH@0&>=WzKqwgV!cF$#Qb=!DV3Nh3S7%}#?Zc?%dA^n#m2X}%d7&w&SF%M|xD%%vj#UY-1V^){H` z`*f-m@nGt8JpP_W@A;JFHQ8#>b@cZsGh2}#E=NnhMu`l-a?H+C3{=?xn3&!J`iUcg zB{IZJocL^es7v^4vl|G=U7cHQYB0hnp`ps!^IHoqgfu08t?dvCi-!o~$p(>wGF>~Q zYig+Z2pd&R;3QF}3^o>G50>I(0`vRixnV`uGyKH}p4tQSh_ZTJ2B9;hR7uPE-|4Og zF6KiGtvvZVNvf+ zlZTyJOIp6u`=Iz8ztA~C(4b0FQnqgLQA`8RI;UxIhA=t}FR|U^rLS3!#=twPylK

>LOY}c{!GbF&61Mkd>7Yps6XCzL5S75Pi{Z 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 delta 33177 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�tYhSAeI|5R0{=tk&I>;=Z(64}Rs!{^w0p|nG>_EfbUIrmR8P`-koJShDb zq-;85I=l|0`?zAQ8rpOENto)AYT>S;SJ3Y09dX16Q|;CJ(G>mng|!L!YSMP;)yHo8 z)h9;^pq`!(32ZPQ*HcB*UFag zwR;sk+Y+?g)O=F1WY96pT9}H7#IY?RRwHkMqg!s+1@{pa;_bV9AQuhGk>QwpJvvKv zb^Dr}f?YaekXmss{N4)~vS5X)-iwpq!%>Dg$=U4HAG+Q1jo~&%QK}(!7oC}$m~9br zklz67Lp@h)8$^ZjJi4w~>CQgNoMbmDhtWb}w=v3K{7%9J;5rPW2UXn{?w`$~cT# zR<7D)<8CvRy3P18ZS|C&wjtNQ_M`V-vaiFnTKj=5237{fB*QLDm%s*^HdqxAT1o)> zE3?xEI04TJ*+9jxc96h)5n6iQt%spH?P-xzbc1$H6VZ)jxHUA}>-P`g6!UX4xokQ3 zaV<68fMPjpPm?tv`p+ zGsq3-+Z#ggLO{sy8Q$kZ#+dFCZMj3mPZ0A%WN``w6Dog}gq8rRxBR!AV-MgLv_m;l zZp;g)6O#EjjOiN@3@ahjJc7!kS}kr6cLiGscM=zM{l1S)1bXE{v?zZ?{&IV%6RK-1#83Qd= zmMWsDqI4HUXA9>*HT(6v4uP8J&5S$an=HVOuU(PCUh=mS<00Gg0{l7Gp3D#M# zfK??lMPxo%Ftk1iAq7ncf?pP)eYpYf5#hAB2+|nI{8}joLShswWod>UPrXGtzCBm~ zL1_n%8}JYE@%n30HGc(i)r8aa&FAd-lJ}|U?QH-^YHv9ZN(i8s?#NNAGfyv2KbWjc zDLFk6G88~D#>`huBqhO*x!%_p++bM^s1!&J{w<7_$MF!J)swhB2Ro4lmUD1GClDL` z03$0ndN*HykWdrCGPgUX#AM=HWhO%&IH z-`1(Bm$KzkXD2O0eT^CP`P)5NYdKR8+8}rGR-*gt_(Q

6g# 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 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); diff --git a/src/de/extio/lm_launcher/Data.java b/src/de/extio/lm_launcher/Data.java index bd6e35a..9b064d4 100644 --- a/src/de/extio/lm_launcher/Data.java +++ b/src/de/extio/lm_launcher/Data.java @@ -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 models) { diff --git a/src/de/extio/lm_launcher/LaunchFrame.java b/src/de/extio/lm_launcher/LaunchFrame.java index 3f85704..1191a93 100644 --- a/src/de/extio/lm_launcher/LaunchFrame.java +++ b/src/de/extio/lm_launcher/LaunchFrame.java @@ -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 createDecimalLabelTable(final int[] values) { + final Hashtable 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() { diff --git a/src/de/extio/lm_launcher/Model.java b/src/de/extio/lm_launcher/Model.java index 089b959..f91a37f 100644 --- a/src/de/extio/lm_launcher/Model.java +++ b/src/de/extio/lm_launcher/Model.java @@ -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(); + } } diff --git a/src/de/extio/lm_launcher/ModelPropertiesDialog.java b/src/de/extio/lm_launcher/ModelPropertiesDialog.java index e37b945..e573958 100644 --- a/src/de/extio/lm_launcher/ModelPropertiesDialog.java +++ b/src/de/extio/lm_launcher/ModelPropertiesDialog.java @@ -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 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,17 +166,30 @@ public class ModelPropertiesDialog extends JDialog { @Override public void actionPerformed(final ActionEvent e) { - 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())); - ModelPropertiesDialog.this.dispose(); + 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); + modelConsumer.accept( + 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"); @@ -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)); + } + } \ No newline at end of file