Add REASONING_EFFORT configuration and UI support
This commit is contained in:
@@ -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
|
||||||
|
|||||||
BIN
lm-launcher.jar
BIN
lm-launcher.jar
Binary file not shown.
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user