import QtCore import QtQuick import QtQuick.Controls import QtQuick.Controls.Basic import QtQuick.Layouts import modellist import mysettings MySettingsTab { onRestoreDefaultsClicked: { MySettings.restoreModelDefaults(root.currentModelInfo); } title: qsTr("Model/Character Settings") contentItem: GridLayout { id: root columns: 3 rowSpacing: 10 columnSpacing: 10 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 font.pixelSize: theme.fontSizeLarge } RowLayout { Layout.fillWidth: true 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 font.pixelSize: theme.fontSizeLarge } 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 font.pixelSize: theme.fontSizeLarge wrapMode: TextArea.Wrap } } MyTextField { id: uniqueNameField text: root.currentModelName font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 4 Layout.column: 0 Layout.topMargin: 15 } MyTextField { text: root.currentModelInfo.filename font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge 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(100, 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 font.pixelSize: theme.fontSizeLarge } Label { id: promptTemplateLabelHelp text: qsTr("Must contain the string \"%1\" to be replaced with the user's input.") color: theme.textErrorColor font.pixelSize: theme.fontSizeLarge 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(100, templateTextArea.contentHeight + 20) color: "transparent" clip: true TextArea { id: templateTextArea anchors.fill: parent text: root.currentModelInfo.promptTemplate color: theme.textColor font.pixelSize: theme.fontSizeLarge 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") font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 0 Layout.column: 0 } MyTextField { id: temperatureField text: root.currentModelInfo.temperature color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 0 Layout.column: 2 } MyTextField { id: topPField text: root.currentModelInfo.topP color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 1 Layout.column: 0 } MyTextField { id: topKField visible: !root.currentModelInfo.isChatGPT text: root.currentModelInfo.topK color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 1 Layout.column: 2 } MyTextField { id: maxLengthField visible: !root.currentModelInfo.isChatGPT text: root.currentModelInfo.maxLength color: theme.textColor font.pixelSize: theme.fontSizeLarge 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:") font.pixelSize: theme.fontSizeLarge color: theme.textColor Layout.row: 2 Layout.column: 0 } MyTextField { id: batchSizeField visible: !root.currentModelInfo.isChatGPT text: root.currentModelInfo.promptBatchSize color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 2 Layout.column: 2 } MyTextField { id: repeatPenaltyField visible: !root.currentModelInfo.isChatGPT text: root.currentModelInfo.repeatPenalty color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 font.pixelSize: theme.fontSizeLarge Layout.row: 3 Layout.column: 0 } MyTextField { id: repeatPenaltyTokenField visible: !root.currentModelInfo.isChatGPT text: root.currentModelInfo.repeatPenaltyTokens color: theme.textColor font.pixelSize: theme.fontSizeLarge 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 } } }