Add REASONING_EFFORT configuration and UI support

This commit is contained in:
extio-de
2026-08-15 16:39:38 +02:00
parent a8ca6f3661
commit a6e57dec5e
8 changed files with 65 additions and 668 deletions

View File

@@ -45,6 +45,7 @@ Use these tokens in app arguments:
- `TOP_P` - `TOP_P`
- `TOP_K` - `TOP_K`
- `MIN_P` - `MIN_P`
- `REASONING_EFFORT`
- `REASONING_STOP` - `REASONING_STOP`
Example: Example:
@@ -53,6 +54,11 @@ Example:
-m MODEL -c CONTEXT_SIZE -t THREADS -ngl GPU_LAYERS --temp TEMP --top-p TOP_P --top-k TOP_K --min-p MIN_P -m MODEL -c CONTEXT_SIZE -t THREADS -ngl GPU_LAYERS --temp TEMP --top-p TOP_P --top-k TOP_K --min-p MIN_P
``` ```
For llama-server reasoning controls, configure `--chat-template-kwargs REASONING_EFFORT`.
The placeholder expands to a single JSON argument such as `{"reasoning_effort": "medium"}`.
When this placeholder is selected for the current app and model, the model options panel provides
the presets `none`, `low`, `medium`, `high`, and `xhigh`.
## Setup ## Setup
### lm-launcher.properties ### lm-launcher.properties

664
apps.json

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -27,6 +27,7 @@ record App(Path path, Path interpreter, @Deprecated List<String> arguments, List
"TOP_P", Model::topPDisplay, "TOP_P", Model::topPDisplay,
"TOP_K", Model::topKDisplay, "TOP_K", Model::topKDisplay,
"MIN_P", Model::minPDisplay, "MIN_P", Model::minPDisplay,
"REASONING_EFFORT", Model::reasoningEffortArgument,
"REASONING_STOP", m -> "... thinking budget exceeded, let's answer now.\n"); "REASONING_STOP", m -> "... thinking budget exceeded, let's answer now.\n");
String argumentsToString(final boolean showAll) { String argumentsToString(final boolean showAll) {

View File

@@ -46,9 +46,9 @@ public class Data {
for (int i = 0; i < modelData.models().size(); i++) { for (int i = 0; i < modelData.models().size(); i++) {
final Model model = modelData.models.get(i); final Model model = modelData.models.get(i);
if (model.maxContextSize() < model.contextSize() || model.promptTemplate() == null || model.temperature() == null || model.topP() == null || model.topK() == null if (model.maxContextSize() < model.contextSize() || model.promptTemplate() == null || model.temperature() == null || model.topP() == null || model.topK() == null
|| model.minP() == null) { || model.minP() == null || model.reasoningEffort() == null) {
modelData.models.set(i, new Model(model.path(), model.contextSize(), model.maxContextSize(), model.gpuLayers(), model.threads(), model.temperature(), model.topP(), model.topK(), 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())); model.minP(), model.promptTemplate(), model.reasoningEffort(), model.ctime()));
} }
} }
sortModels(); sortModels();
@@ -168,7 +168,7 @@ public class Data {
catch (final IOException e) { catch (final IOException e) {
// Use 0 as fallback // Use 0 as fallback
} }
return new Model(path, 16000, 128000, 99, 6, Model.DEFAULT_TEMPERATURE, Model.DEFAULT_TOP_P, Model.DEFAULT_TOP_K, Model.DEFAULT_MIN_P, "", ctime); return new Model(path, 16000, 128000, 99, 6, Model.DEFAULT_TEMPERATURE, Model.DEFAULT_TOP_P, Model.DEFAULT_TOP_K, Model.DEFAULT_MIN_P, "", Model.DEFAULT_REASONING_EFFORT, ctime);
} }
static record ModelData(List<Model> models) { static record ModelData(List<Model> models) {

View File

@@ -21,6 +21,7 @@ import javax.swing.DefaultListModel;
import javax.swing.DefaultListSelectionModel; import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
@@ -152,6 +153,10 @@ public class LaunchFrame extends JFrame {
JSlider slider_minP; JSlider slider_minP;
JLabel lblMinPValue; JLabel lblMinPValue;
JLabel lblReasoningEffort;
JComboBox<String> comboReasoningEffort;
/** /**
* Create the frame. * Create the frame.
@@ -431,6 +436,16 @@ public class LaunchFrame extends JFrame {
this.lblMinPValue.setHorizontalAlignment(SwingConstants.CENTER); this.lblMinPValue.setHorizontalAlignment(SwingConstants.CENTER);
this.panel_3.add(this.lblMinPValue); this.panel_3.add(this.lblMinPValue);
} }
{
this.lblReasoningEffort = new JLabel("Reasoning Effort");
this.lblReasoningEffort.setHorizontalAlignment(SwingConstants.CENTER);
this.panel_3.add(this.lblReasoningEffort);
}
{
this.comboReasoningEffort = new JComboBox<>(Model.REASONING_EFFORTS);
this.comboReasoningEffort.setSelectedItem(Model.DEFAULT_REASONING_EFFORT);
this.panel_3.add(this.comboReasoningEffort);
}
{ {
this.verticalStrut = Box.createVerticalStrut(20); this.verticalStrut = Box.createVerticalStrut(20);
this.panel_3.add(this.verticalStrut); this.panel_3.add(this.verticalStrut);
@@ -571,6 +586,7 @@ public class LaunchFrame extends JFrame {
LaunchFrame.this.slider_topK.getValue(), LaunchFrame.this.slider_topK.getValue(),
LaunchFrame.this.sliderValue(LaunchFrame.this.slider_minP), LaunchFrame.this.sliderValue(LaunchFrame.this.slider_minP),
template.promptTemplate(), template.promptTemplate(),
(String) LaunchFrame.this.comboReasoningEffort.getSelectedItem(),
template.ctime()); template.ctime());
} }
@@ -639,10 +655,12 @@ public class LaunchFrame extends JFrame {
this.appArgumentsTableModel.setRowCount(0); this.appArgumentsTableModel.setRowCount(0);
final App selectedApp = this.getSelectedApp(); final App selectedApp = this.getSelectedApp();
if (selectedApp == null) { if (selectedApp == null) {
this.updateReasoningEffortVisibility();
return; return;
} }
selectedApp.argumentsForModel(this.getSelectedModelPath()) selectedApp.argumentsForModel(this.getSelectedModelPath())
.forEach(argument -> this.appArgumentsTableModel.addRow(new Object[] { argument })); .forEach(argument -> this.appArgumentsTableModel.addRow(new Object[] { argument }));
this.updateReasoningEffortVisibility();
} }
private List<AppArgument> currentTableArguments() { private List<AppArgument> currentTableArguments() {
@@ -671,9 +689,25 @@ public class LaunchFrame extends JFrame {
this.slider_topP.setValue(LaunchFrame.doubleToSlider(model.topPValue())); this.slider_topP.setValue(LaunchFrame.doubleToSlider(model.topPValue()));
this.slider_topK.setValue(model.topKValue()); this.slider_topK.setValue(model.topKValue());
this.slider_minP.setValue(LaunchFrame.doubleToSlider(model.minPValue())); this.slider_minP.setValue(LaunchFrame.doubleToSlider(model.minPValue()));
this.comboReasoningEffort.setSelectedItem(model.reasoningEffort());
this.lblPromptTemplate_1.setText(model.promptTemplate() != null && !model.promptTemplate().isEmpty() ? model.promptTemplate() : "-"); this.lblPromptTemplate_1.setText(model.promptTemplate() != null && !model.promptTemplate().isEmpty() ? model.promptTemplate() : "-");
this.updateSamplingValueLabels(); this.updateSamplingValueLabels();
} }
private void updateReasoningEffortVisibility() {
boolean selected = false;
for (int i = 0; i < this.appArgumentsTableModel.getRowCount(); i++) {
final AppArgument argument = (AppArgument) this.appArgumentsTableModel.getValueAt(i, 0);
if ("REASONING_EFFORT".equals(argument.argument()) && (!argument.optional() || argument.default_())) {
selected = true;
break;
}
}
this.lblReasoningEffort.setVisible(selected);
this.comboReasoningEffort.setVisible(selected);
this.panel_3.revalidate();
this.panel_3.repaint();
}
private void updateSamplingValueLabels() { private void updateSamplingValueLabels() {
this.lblTemperatureValue.setText(Model.formatDecimal(this.sliderValue(this.slider_temperature))); this.lblTemperatureValue.setText(Model.formatDecimal(this.sliderValue(this.slider_temperature)));

View File

@@ -3,7 +3,11 @@ package de.extio.lm_launcher;
import java.math.BigDecimal; import java.math.BigDecimal;
record Model(String path, int contextSize, int maxContextSize, int gpuLayers, int threads, Double temperature, Double topP, record Model(String path, int contextSize, int maxContextSize, int gpuLayers, int threads, Double temperature, Double topP,
Integer topK, Double minP, String promptTemplate, long ctime) { Integer topK, Double minP, String promptTemplate, String reasoningEffort, long ctime) {
static final String[] REASONING_EFFORTS = { "none", "low", "medium", "high", "xhigh" };
static final String DEFAULT_REASONING_EFFORT = "medium";
static final double DEFAULT_TEMPERATURE = 0.8d; static final double DEFAULT_TEMPERATURE = 0.8d;
@@ -39,6 +43,20 @@ record Model(String path, int contextSize, int maxContextSize, int gpuLayers, in
topK = sanitizeInt(topK, DEFAULT_TOP_K, MIN_TOP_K, MAX_TOP_K); topK = sanitizeInt(topK, DEFAULT_TOP_K, MIN_TOP_K, MAX_TOP_K);
minP = sanitizeDouble(minP, DEFAULT_MIN_P, MIN_MIN_P, MAX_MIN_P); minP = sanitizeDouble(minP, DEFAULT_MIN_P, MIN_MIN_P, MAX_MIN_P);
promptTemplate = promptTemplate == null ? "" : promptTemplate; promptTemplate = promptTemplate == null ? "" : promptTemplate;
reasoningEffort = isValidReasoningEffort(reasoningEffort) ? reasoningEffort : DEFAULT_REASONING_EFFORT;
}
String reasoningEffortArgument() {
return "{\"reasoning_effort\": \"" + this.reasoningEffort + "\"}";
}
private static boolean isValidReasoningEffort(final String value) {
for (final String effort : REASONING_EFFORTS) {
if (effort.equals(value)) {
return true;
}
}
return false;
} }
double temperatureValue() { double temperatureValue() {

View File

@@ -184,7 +184,7 @@ public class ModelPropertiesDialog extends JDialog {
ModelPropertiesDialog.this.setVisible(false); ModelPropertiesDialog.this.setVisible(false);
modelConsumer.accept( modelConsumer.accept(
new Model(modelPath, contextSize, maxContextSize, gpuLayers, threads, temperature, topP, topK, minP, ModelPropertiesDialog.this.txtPrompttemplate.getText(), new Model(modelPath, contextSize, maxContextSize, gpuLayers, threads, temperature, topP, topK, minP, ModelPropertiesDialog.this.txtPrompttemplate.getText(),
modelToEdit.ctime())); modelToEdit.reasoningEffort(), modelToEdit.ctime()));
ModelPropertiesDialog.this.dispose(); ModelPropertiesDialog.this.dispose();
} }
catch (final NumberFormatException nfe) { catch (final NumberFormatException nfe) {