mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-09-01 08:38:35 +00:00
Huge change that completely revamps the settings dialog and implements
per model settings as well as the ability to clone a model into a "character." This also implements system prompts as well as quite a few bugfixes for instance this fixes chatgpt.
This commit is contained in:
@@ -3,27 +3,665 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import localdocs
|
||||
import modellist
|
||||
import mysettings
|
||||
|
||||
MySettingsTab {
|
||||
title: qsTr("Models")
|
||||
onRestoreDefaultsClicked: {
|
||||
MySettings.restoreModelDefaults(root.currentModelInfo);
|
||||
}
|
||||
title: qsTr("Model/Character Settings")
|
||||
contentItem: GridLayout {
|
||||
id: generationSettingsTabInner
|
||||
columns: 2
|
||||
id: root
|
||||
columns: 3
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
|
||||
MyButton {
|
||||
Layout.row: 8
|
||||
Layout.column: 1
|
||||
property var currentModelName: comboBox.currentText
|
||||
property var currentModelId: comboBox.currentValue
|
||||
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
|
||||
|
||||
Label {
|
||||
id: label
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
text: qsTr("Model/Character:")
|
||||
color: theme.textColor
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Restore Defaults")
|
||||
Accessible.description: qsTr("Restores the settings dialog to a default state")
|
||||
onClicked: {
|
||||
MySettings.restoreGenerationDefaults();
|
||||
templateTextArea.text = MySettings.promptTemplate
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
height: label.height + 20
|
||||
spacing: 10
|
||||
|
||||
MyComboBox {
|
||||
id: comboBox
|
||||
Layout.fillWidth: true
|
||||
model: ModelList.installedModels
|
||||
valueRole: "id"
|
||||
textRole: "name"
|
||||
currentIndex: 0
|
||||
contentItem: Text {
|
||||
leftPadding: 10
|
||||
rightPadding: 20
|
||||
text: comboBox.currentText
|
||||
font: comboBox.font
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
delegate: ItemDelegate {
|
||||
width: comboBox.width
|
||||
contentItem: Text {
|
||||
text: name
|
||||
color: theme.textColor
|
||||
font: comboBox.font
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
background: Rectangle {
|
||||
color: highlighted ? theme.backgroundLight : theme.backgroundDark
|
||||
}
|
||||
highlighted: comboBox.highlightedIndex === index
|
||||
}
|
||||
}
|
||||
|
||||
MyButton {
|
||||
id: cloneButton
|
||||
text: qsTr("Clone")
|
||||
onClicked: {
|
||||
var id = ModelList.clone(root.currentModelInfo);
|
||||
comboBox.currentIndex = comboBox.indexOfValue(id);
|
||||
}
|
||||
}
|
||||
|
||||
MyButton {
|
||||
id: removeButton
|
||||
enabled: root.currentModelInfo.isClone
|
||||
text: qsTr("Remove")
|
||||
onClicked: {
|
||||
ModelList.remove(root.currentModelInfo);
|
||||
comboBox.currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
Layout.topMargin: 15
|
||||
spacing: 10
|
||||
Label {
|
||||
id: uniqueNameLabel
|
||||
text: qsTr("Unique Name:")
|
||||
color: theme.textColor
|
||||
}
|
||||
Label {
|
||||
id: uniqueNameLabelHelp
|
||||
visible: false
|
||||
text: qsTr("Must contain a non-empty unique name that does not match any existing model/character.")
|
||||
color: theme.textErrorColor
|
||||
wrapMode: TextArea.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
MyTextField {
|
||||
id: uniqueNameField
|
||||
text: root.currentModelName
|
||||
enabled: root.currentModelInfo.isClone || root.currentModelInfo.description === ""
|
||||
color: enabled ? theme.textColor : theme.mutedTextColor
|
||||
Layout.row: 3
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onNameChanged() {
|
||||
uniqueNameField.text = root.currentModelInfo.name;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
uniqueNameField.text = root.currentModelInfo.name;
|
||||
}
|
||||
}
|
||||
onTextChanged: {
|
||||
if (text !== "" && ModelList.isUniqueName(text)) {
|
||||
MySettings.setModelName(root.currentModelInfo, text);
|
||||
}
|
||||
uniqueNameLabelHelp.visible = root.currentModelInfo.name !== "" &&
|
||||
(text === "" || (text !== root.currentModelInfo.name && !ModelList.isUniqueName(text)));
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Model File:")
|
||||
color: theme.textColor
|
||||
Layout.row: 4
|
||||
Layout.column: 0
|
||||
Layout.topMargin: 15
|
||||
}
|
||||
|
||||
MyTextField {
|
||||
text: root.currentModelInfo.filename
|
||||
enabled: false
|
||||
color: enabled ? theme.textColor : theme.mutedTextColor
|
||||
Layout.row: 5
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("System Prompt:")
|
||||
color: theme.textColor
|
||||
Layout.row: 6
|
||||
Layout.column: 0
|
||||
Layout.topMargin: 15
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: systemPrompt
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
Layout.row: 7
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
color: "transparent"
|
||||
Layout.minimumHeight: Math.max(150, systemPromptArea.contentHeight + 20)
|
||||
TextArea {
|
||||
id: systemPromptArea
|
||||
anchors.fill: parent
|
||||
text: root.currentModelInfo.systemPrompt
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundDark
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
wrapMode: TextArea.Wrap
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onSystemPromptChanged() {
|
||||
systemPromptArea.text = root.currentModelInfo.systemPrompt;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
systemPromptArea.text = root.currentModelInfo.systemPrompt;
|
||||
}
|
||||
}
|
||||
onTextChanged: {
|
||||
MySettings.setModelSystemPrompt(root.currentModelInfo, text)
|
||||
}
|
||||
bottomPadding: 10
|
||||
Accessible.role: Accessible.EditableText
|
||||
ToolTip.text: qsTr("The systemPrompt allows instructions to the model at the beginning of a chat.\nNOTE: A longer, detailed system prompt can lead to higher quality answers, but can also slow down generation.")
|
||||
ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.row: 8
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: 15
|
||||
spacing: 10
|
||||
Label {
|
||||
id: promptTemplateLabel
|
||||
text: qsTr("Prompt Template:")
|
||||
color: theme.textColor
|
||||
}
|
||||
Label {
|
||||
id: promptTemplateLabelHelp
|
||||
text: qsTr("Must contain the string \"%1\" to be replaced with the user's input.")
|
||||
color: theme.textErrorColor
|
||||
visible: templateTextArea.text.indexOf("%1") === -1
|
||||
wrapMode: TextArea.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: promptTemplate
|
||||
Layout.row: 9
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: Math.max(150, templateTextArea.contentHeight + 20)
|
||||
color: "transparent"
|
||||
clip: true
|
||||
TextArea {
|
||||
id: templateTextArea
|
||||
anchors.fill: parent
|
||||
text: root.currentModelInfo.promptTemplate
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundDark
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
wrapMode: TextArea.Wrap
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onPromptTemplateChanged() {
|
||||
templateTextArea.text = root.currentModelInfo.promptTemplate;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
templateTextArea.text = root.currentModelInfo.promptTemplate;
|
||||
}
|
||||
}
|
||||
onTextChanged: {
|
||||
if (templateTextArea.text.indexOf("%1") !== -1) {
|
||||
MySettings.setModelPromptTemplate(root.currentModelInfo, text)
|
||||
}
|
||||
}
|
||||
bottomPadding: 10
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: promptTemplateLabel.text
|
||||
Accessible.description: promptTemplateLabelHelp.text
|
||||
ToolTip.text: qsTr("The prompt template partially determines how models will respond to prompts.\nNOTE: A longer, detailed template can lead to higher quality answers, but can also slow down generation.")
|
||||
ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: optionalImageRect
|
||||
visible: false // FIXME: for later
|
||||
Layout.row: 2
|
||||
Layout.column: 1
|
||||
Layout.rowSpan: 5
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillHeight: true
|
||||
Layout.maximumWidth: height
|
||||
Layout.topMargin: 35
|
||||
Layout.bottomMargin: 35
|
||||
Layout.leftMargin: 35
|
||||
width: 3000
|
||||
border.width: 1
|
||||
border.color: theme.tabBorder
|
||||
radius: 10
|
||||
color: "transparent"
|
||||
Item {
|
||||
anchors.centerIn: parent
|
||||
height: childrenRect.height
|
||||
Image {
|
||||
id: img
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 100
|
||||
height: 100
|
||||
source: "qrc:/gpt4all/icons/image.svg"
|
||||
}
|
||||
Text {
|
||||
text: qsTr("Add\noptional image")
|
||||
anchors.top: img.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
wrapMode: TextArea.Wrap
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
color: theme.mutedTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Generation Settings")
|
||||
color: theme.textColor
|
||||
Layout.row: 10
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: 15
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.minimumWidth: promptTemplate.width
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.row: 11
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: 15
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: promptTemplate.width
|
||||
columns: 4
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
|
||||
Label {
|
||||
id: tempLabel
|
||||
text: qsTr("Temperature:")
|
||||
color: theme.textColor
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
}
|
||||
|
||||
MyTextField {
|
||||
id: temperatureField
|
||||
text: root.currentModelInfo.temperature
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Temperature increases the chances of choosing less likely tokens.\nNOTE: Higher temperature gives more creative but less predictable outputs.")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 0
|
||||
Layout.column: 1
|
||||
validator: DoubleValidator {
|
||||
locale: "C"
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onTemperatureChanged() {
|
||||
temperatureField.text = root.currentModelInfo.temperature;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
temperatureField.text = root.currentModelInfo.temperature;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseFloat(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelTemperature(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.temperature
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: tempLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: topPLabel
|
||||
text: qsTr("Top P:")
|
||||
color: theme.textColor
|
||||
Layout.row: 0
|
||||
Layout.column: 2
|
||||
}
|
||||
MyTextField {
|
||||
id: topPField
|
||||
text: root.currentModelInfo.topP
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens, aka Nucleus Sampling")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 0
|
||||
Layout.column: 3
|
||||
validator: DoubleValidator {
|
||||
locale: "C"
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onTopPChanged() {
|
||||
topPField.text = root.currentModelInfo.topP;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
topPField.text = root.currentModelInfo.topP;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseFloat(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelTopP(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.topP
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: topPLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: topKLabel
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("Top K:")
|
||||
color: theme.textColor
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
}
|
||||
MyTextField {
|
||||
id: topKField
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: root.currentModelInfo.topK
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 1
|
||||
Layout.column: 1
|
||||
validator: IntValidator {
|
||||
bottom: 1
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onTopKChanged() {
|
||||
topKField.text = root.currentModelInfo.topK;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
topKField.text = root.currentModelInfo.topK;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseInt(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelTopK(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.topK
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: topKLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: maxLengthLabel
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("Max Length:")
|
||||
color: theme.textColor
|
||||
Layout.row: 1
|
||||
Layout.column: 2
|
||||
}
|
||||
MyTextField {
|
||||
id: maxLengthField
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: root.currentModelInfo.maxLength
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Maximum length of response in tokens")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 1
|
||||
Layout.column: 3
|
||||
validator: IntValidator {
|
||||
bottom: 1
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onMaxLengthChanged() {
|
||||
maxLengthField.text = root.currentModelInfo.maxLength;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
maxLengthField.text = root.currentModelInfo.maxLength;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseInt(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelMaxLength(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.maxLength
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: maxLengthLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
|
||||
Label {
|
||||
id: batchSizeLabel
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("Prompt Batch Size:")
|
||||
color: theme.textColor
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
}
|
||||
MyTextField {
|
||||
id: batchSizeField
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: root.currentModelInfo.promptBatchSize
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 2
|
||||
Layout.column: 1
|
||||
validator: IntValidator {
|
||||
bottom: 1
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onPromptBatchSizeChanged() {
|
||||
batchSizeField.text = root.currentModelInfo.promptBatchSize;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
batchSizeField.text = root.currentModelInfo.promptBatchSize;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseInt(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelPromptBatchSize(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.promptBatchSize
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: batchSizeLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: repeatPenaltyLabel
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("Repeat Penalty:")
|
||||
color: theme.textColor
|
||||
Layout.row: 2
|
||||
Layout.column: 2
|
||||
}
|
||||
MyTextField {
|
||||
id: repeatPenaltyField
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: root.currentModelInfo.repeatPenalty
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 2
|
||||
Layout.column: 3
|
||||
validator: DoubleValidator {
|
||||
locale: "C"
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onRepeatPenaltyChanged() {
|
||||
repeatPenaltyField.text = root.currentModelInfo.repeatPenalty;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
repeatPenaltyField.text = root.currentModelInfo.repeatPenalty;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseFloat(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelRepeatPenalty(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.repeatPenalty
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: repeatPenaltyLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: repeatPenaltyTokensLabel
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: qsTr("Repeat Penalty Tokens:")
|
||||
color: theme.textColor
|
||||
Layout.row: 3
|
||||
Layout.column: 0
|
||||
}
|
||||
MyTextField {
|
||||
id: repeatPenaltyTokenField
|
||||
visible: !root.currentModelInfo.isChatGPT
|
||||
text: root.currentModelInfo.repeatPenaltyTokens
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("How far back in output to apply repeat penalty")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 3
|
||||
Layout.column: 1
|
||||
validator: IntValidator {
|
||||
bottom: 1
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onRepeatPenaltyTokensChanged() {
|
||||
repeatPenaltyTokenField.text = root.currentModelInfo.repeatPenaltyTokens;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
function onCurrentModelInfoChanged() {
|
||||
repeatPenaltyTokenField.text = root.currentModelInfo.repeatPenaltyTokens;
|
||||
}
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseInt(text)
|
||||
if (!isNaN(val)) {
|
||||
MySettings.setModelRepeatPenaltyTokens(root.currentModelInfo, val)
|
||||
focus = false
|
||||
} else {
|
||||
text = root.currentModelInfo.repeatPenaltyTokens
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: repeatPenaltyTokensLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.row: 12
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: 15
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: promptTemplate.width
|
||||
height: 1
|
||||
color: theme.tabBorder
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user