gpt4all/gpt4all-chat/qml/ModelSettings.qml
Jared Van Bortel 225bf6be93
Remove binary state from high-level API and use Jinja templates (#3147)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
Signed-off-by: Adam Treat <treat.adam@gmail.com>
Co-authored-by: Adam Treat <treat.adam@gmail.com>
2024-11-25 10:04:17 -05:00

1000 lines
41 KiB
QML

import QtCore
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Layouts
import modellist
import mysettings
import chatlistmodel
MySettingsTab {
onRestoreDefaults: {
MySettings.restoreModelDefaults(root.currentModelInfo);
}
title: qsTr("Model")
ConfirmationDialog {
id: resetSystemMessageDialog
property var index: null
property bool resetClears: false
dialogTitle: qsTr("%1 system message?").arg(resetClears ? qsTr("Clear") : qsTr("Reset"))
description: qsTr("The system message will be %1.").arg(resetClears ? qsTr("removed") : qsTr("reset to the default"))
onAccepted: MySettings.resetModelSystemMessage(ModelList.modelInfo(index))
function show(index_, resetClears_) { index = index_; resetClears = resetClears_; open(); }
}
ConfirmationDialog {
id: resetChatTemplateDialog
property bool resetClears: false
property var index: null
dialogTitle: qsTr("%1 chat template?").arg(resetClears ? qsTr("Clear") : qsTr("Reset"))
description: qsTr("The chat template will be %1.").arg(resetClears ? qsTr("erased") : qsTr("reset to the default"))
onAccepted: {
MySettings.resetModelChatTemplate(ModelList.modelInfo(index));
templateTextArea.resetText();
}
function show(index_, resetClears_) { index = index_; resetClears = resetClears_; open(); }
}
contentItem: GridLayout {
id: root
columns: 3
rowSpacing: 10
columnSpacing: 10
enabled: ModelList.selectableModels.count !== 0
property var currentModelName: comboBox.currentText
property var currentModelId: comboBox.currentValue
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
Label {
Layout.row: 1
Layout.column: 0
Layout.bottomMargin: 10
color: theme.settingsTitleTextColor
font.pixelSize: theme.fontSizeBannerSmall
font.bold: true
text: qsTr("Model Settings")
}
RowLayout {
Layout.fillWidth: true
Layout.maximumWidth: parent.width
Layout.row: 2
Layout.column: 0
Layout.columnSpan: 2
spacing: 10
MyComboBox {
id: comboBox
Layout.fillWidth: true
model: ModelList.selectableModels
valueRole: "id"
textRole: "name"
currentIndex: {
var i = comboBox.indexOfValue(ChatListModel.currentChat.modelInfo.id);
if (i >= 0)
return i;
return 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 -20
contentItem: Text {
text: name
color: theme.textColor
font: comboBox.font
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
radius: 10
color: highlighted ? theme.menuHighlightColor : theme.menuBackgroundColor
}
highlighted: comboBox.highlightedIndex === index
}
}
MySettingsButton {
id: cloneButton
text: qsTr("Clone")
onClicked: {
var id = ModelList.clone(root.currentModelInfo);
comboBox.currentIndex = comboBox.indexOfValue(id);
}
}
MySettingsDestructiveButton {
id: removeButton
enabled: root.currentModelInfo.isClone
text: qsTr("Remove")
onClicked: {
ModelList.removeClone(root.currentModelInfo);
comboBox.currentIndex = 0;
}
}
}
RowLayout {
Layout.row: 3
Layout.column: 0
Layout.topMargin: 15
spacing: 10
MySettingsLabel {
text: qsTr("Name")
}
}
MyTextField {
id: uniqueNameField
text: root.currentModelName
font.pixelSize: theme.fontSizeLarge
enabled: root.currentModelInfo.isClone || root.currentModelInfo.description === ""
Layout.row: 4
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);
}
}
}
MySettingsLabel {
text: qsTr("Model File")
Layout.row: 5
Layout.column: 0
Layout.topMargin: 15
}
MyTextField {
text: root.currentModelInfo.filename
font.pixelSize: theme.fontSizeLarge
enabled: false
Layout.row: 6
Layout.column: 0
Layout.columnSpan: 2
Layout.fillWidth: true
}
RowLayout {
Layout.row: 7
Layout.columnSpan: 2
Layout.topMargin: 15
Layout.fillWidth: true
Layout.maximumWidth: parent.width
spacing: 10
MySettingsLabel {
id: systemMessageLabel
text: qsTr("System Message")
helpText: qsTr("A message to set the context or guide the behavior of the model. Leave blank for " +
"none. NOTE: Since GPT4All 3.5, this should not contain control tokens.")
onReset: () => resetSystemMessageDialog.show(root.currentModelId, resetClears)
function updateResetButton() {
const info = root.currentModelInfo;
// NOTE: checks if the *override* is set, regardless of whether there is a default
canReset = !!info.id && MySettings.isModelSystemMessageSet(info);
resetClears = !info.defaultSystemMessage;
}
Component.onCompleted: updateResetButton()
Connections {
target: root
function onCurrentModelIdChanged() { systemMessageLabel.updateResetButton(); }
}
Connections {
target: MySettings
function onSystemMessageChanged(info)
{ if (info.id === root.currentModelId) systemMessageLabel.updateResetButton(); }
}
}
Label {
id: systemMessageLabelHelp
visible: systemMessageArea.errState !== "ok"
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Layout.rightMargin: 5
Layout.maximumHeight: systemMessageLabel.height
text: qsTr("System message is not " +
"<a href=\"https://docs.gpt4all.io/gpt4all_desktop/chat_templates.html\">plain text</a>.")
color: systemMessageArea.errState === "error" ? theme.textErrorColor : theme.textWarningColor
font.pixelSize: theme.fontSizeLarger
font.bold: true
wrapMode: Text.Wrap
elide: Text.ElideRight
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
}
}
Rectangle {
id: systemMessage
Layout.row: 8
Layout.column: 0
Layout.columnSpan: 2
Layout.fillWidth: true
color: "transparent"
Layout.minimumHeight: Math.max(100, systemMessageArea.contentHeight + 20)
MyTextArea {
id: systemMessageArea
anchors.fill: parent
property bool isBeingReset: false
function resetText() {
const info = root.currentModelInfo;
isBeingReset = true;
text = (info.id ? info.systemMessage.value : null) ?? "";
isBeingReset = false;
}
Component.onCompleted: resetText()
Connections {
target: MySettings
function onSystemMessageChanged(info)
{ if (info.id === root.currentModelId) systemMessageArea.resetText(); }
}
Connections {
target: root
function onCurrentModelIdChanged() { systemMessageArea.resetText(); }
}
// strict validation, because setModelSystemMessage clears isLegacy
readonly property var reLegacyCheck: (
/(?:^|\s)(?:### *System\b|S(?:ystem|YSTEM):)|<\|(?:im_(?:start|end)|(?:start|end)_header_id|eot_id|SYSTEM_TOKEN)\|>|<<SYS>>/m
)
onTextChanged: {
const info = root.currentModelInfo;
if (!info.id) {
errState = "ok";
} else if (info.systemMessage.isLegacy && (isBeingReset || reLegacyCheck.test(text))) {
errState = "error";
} else
errState = reLegacyCheck.test(text) ? "warning" : "ok";
if (info.id && errState !== "error" && !isBeingReset)
MySettings.setModelSystemMessage(info, text);
systemMessageLabel.updateResetButton();
}
Accessible.role: Accessible.EditableText
Accessible.name: systemMessageLabel.text
Accessible.description: systemMessageLabelHelp.text
}
}
RowLayout {
Layout.row: 9
Layout.columnSpan: 2
Layout.topMargin: 15
Layout.fillWidth: true
Layout.maximumWidth: parent.width
spacing: 10
MySettingsLabel {
id: chatTemplateLabel
text: qsTr("Chat Template")
helpText: qsTr("This Jinja template turns the chat into input for the model.")
onReset: () => resetChatTemplateDialog.show(root.currentModelId, resetClears)
function updateResetButton() {
const info = root.currentModelInfo;
canReset = !!info.id && (
MySettings.isModelChatTemplateSet(info)
|| templateTextArea.text !== (info.chatTemplate.value ?? "")
);
resetClears = !info.defaultChatTemplate;
}
Component.onCompleted: updateResetButton()
Connections {
target: root
function onCurrentModelIdChanged() { chatTemplateLabel.updateResetButton(); }
}
Connections {
target: MySettings
function onChatTemplateChanged(info)
{ if (info.id === root.currentModelId) chatTemplateLabel.updateResetButton(); }
}
}
Label {
id: chatTemplateLabelHelp
visible: templateTextArea.errState !== "ok"
Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true
Layout.rightMargin: 5
Layout.maximumHeight: chatTemplateLabel.height
text: templateTextArea.errMsg
color: templateTextArea.errState === "error" ? theme.textErrorColor : theme.textWarningColor
font.pixelSize: theme.fontSizeLarger
font.bold: true
wrapMode: Text.Wrap
elide: Text.ElideRight
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
}
}
Rectangle {
id: chatTemplate
Layout.row: 10
Layout.column: 0
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.minimumHeight: Math.max(100, templateTextArea.contentHeight + 20)
color: "transparent"
clip: true
MyTextArea {
id: templateTextArea
anchors.fill: parent
font: fixedFont
property bool isBeingReset: false
property var errMsg: null
function resetText() {
const info = root.currentModelInfo;
isBeingReset = true;
text = (info.id ? info.chatTemplate.value : null) ?? "";
isBeingReset = false;
}
Component.onCompleted: resetText()
Connections {
target: MySettings
function onChatTemplateChanged() { templateTextArea.resetText(); }
}
Connections {
target: root
function onCurrentModelIdChanged() { templateTextArea.resetText(); }
}
function legacyCheck() {
return /%[12]\b/.test(text) || !/\{%.*%\}.*\{\{.*\}\}.*\{%.*%\}/.test(text.replace(/\n/g, ''))
|| !/\bcontent\b/.test(text);
}
onTextChanged: {
const info = root.currentModelInfo;
let jinjaError;
if (!info.id) {
errMsg = null;
errState = "ok";
} else if (info.chatTemplate.isLegacy && (isBeingReset || legacyCheck())) {
errMsg = null;
errState = "error";
} else if (text === "" && !info.chatTemplate.isSet) {
errMsg = qsTr("No <a href=\"https://docs.gpt4all.io/gpt4all_desktop/chat_templates.html\">" +
"chat template</a> configured.");
errState = "error";
} else if (/^\s*$/.test(text)) {
errMsg = qsTr("The <a href=\"https://docs.gpt4all.io/gpt4all_desktop/chat_templates.html\">" +
"chat template</a> cannot be blank.");
errState = "error";
} else if ((jinjaError = MySettings.checkJinjaTemplateError(text)) !== null) {
errMsg = qsTr("<a href=\"https://docs.gpt4all.io/gpt4all_desktop/chat_templates.html\">Syntax" +
" error</a>: %1").arg(jinjaError);
errState = "error";
} else if (legacyCheck()) {
errMsg = qsTr("Chat template is not in " +
"<a href=\"https://docs.gpt4all.io/gpt4all_desktop/chat_templates.html\">" +
"Jinja format</a>.")
errState = "warning";
} else {
errState = "ok";
}
if (info.id && errState !== "error" && !isBeingReset)
MySettings.setModelChatTemplate(info, text);
chatTemplateLabel.updateResetButton();
}
Keys.onPressed: event => {
if (event.key === Qt.Key_Tab) {
const a = templateTextArea;
event.accepted = true; // suppress tab
a.insert(a.cursorPosition, ' '); // four spaces
}
}
Accessible.role: Accessible.EditableText
Accessible.name: chatTemplateLabel.text
Accessible.description: chatTemplateLabelHelp.text
}
}
MySettingsLabel {
id: chatNamePromptLabel
text: qsTr("Chat Name Prompt")
helpText: qsTr("Prompt used to automatically generate chat names.")
Layout.row: 11
Layout.column: 0
Layout.topMargin: 15
}
Rectangle {
id: chatNamePrompt
Layout.row: 12
Layout.column: 0
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.minimumHeight: Math.max(100, chatNamePromptTextArea.contentHeight + 20)
color: "transparent"
clip: true
MyTextArea {
id: chatNamePromptTextArea
anchors.fill: parent
text: root.currentModelInfo.chatNamePrompt
Connections {
target: MySettings
function onChatNamePromptChanged() {
chatNamePromptTextArea.text = root.currentModelInfo.chatNamePrompt;
}
}
Connections {
target: root
function onCurrentModelInfoChanged() {
chatNamePromptTextArea.text = root.currentModelInfo.chatNamePrompt;
}
}
onTextChanged: {
MySettings.setModelChatNamePrompt(root.currentModelInfo, text)
}
Accessible.role: Accessible.EditableText
Accessible.name: chatNamePromptLabel.text
Accessible.description: chatNamePromptLabel.text
}
}
MySettingsLabel {
id: suggestedFollowUpPromptLabel
text: qsTr("Suggested FollowUp Prompt")
helpText: qsTr("Prompt used to generate suggested follow-up questions.")
Layout.row: 13
Layout.column: 0
Layout.topMargin: 15
}
Rectangle {
id: suggestedFollowUpPrompt
Layout.row: 14
Layout.column: 0
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.minimumHeight: Math.max(100, suggestedFollowUpPromptTextArea.contentHeight + 20)
color: "transparent"
clip: true
MyTextArea {
id: suggestedFollowUpPromptTextArea
anchors.fill: parent
text: root.currentModelInfo.suggestedFollowUpPrompt
Connections {
target: MySettings
function onSuggestedFollowUpPromptChanged() {
suggestedFollowUpPromptTextArea.text = root.currentModelInfo.suggestedFollowUpPrompt;
}
}
Connections {
target: root
function onCurrentModelInfoChanged() {
suggestedFollowUpPromptTextArea.text = root.currentModelInfo.suggestedFollowUpPrompt;
}
}
onTextChanged: {
MySettings.setModelSuggestedFollowUpPrompt(root.currentModelInfo, text)
}
Accessible.role: Accessible.EditableText
Accessible.name: suggestedFollowUpPromptLabel.text
Accessible.description: suggestedFollowUpPromptLabel.text
}
}
GridLayout {
Layout.row: 15
Layout.column: 0
Layout.columnSpan: 2
Layout.topMargin: 15
Layout.fillWidth: true
columns: 4
rowSpacing: 30
columnSpacing: 10
MySettingsLabel {
id: contextLengthLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Context Length")
helpText: qsTr("Number of input and output tokens the model sees.")
Layout.row: 0
Layout.column: 0
Layout.maximumWidth: 300 * theme.fontScale
}
Item {
Layout.row: 0
Layout.column: 1
Layout.fillWidth: true
Layout.maximumWidth: 200
Layout.margins: 0
height: contextLengthField.height
MyTextField {
id: contextLengthField
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
visible: !root.currentModelInfo.isOnline
text: root.currentModelInfo.contextLength
font.pixelSize: theme.fontSizeLarge
color: theme.textColor
ToolTip.text: qsTr("Maximum combined prompt/response tokens before information is lost.\nUsing more context than the model was trained on will yield poor results.\nNOTE: Does not take effect until you reload the model.")
ToolTip.visible: hovered
Connections {
target: MySettings
function onContextLengthChanged() {
contextLengthField.text = root.currentModelInfo.contextLength;
}
}
Connections {
target: root
function onCurrentModelInfoChanged() {
contextLengthField.text = root.currentModelInfo.contextLength;
}
}
onEditingFinished: {
var val = parseInt(text)
if (isNaN(val)) {
text = root.currentModelInfo.contextLength
} else {
if (val < 8) {
val = 8
contextLengthField.text = val
} else if (val > root.currentModelInfo.maxContextLength) {
val = root.currentModelInfo.maxContextLength
contextLengthField.text = val
}
MySettings.setModelContextLength(root.currentModelInfo, val)
focus = false
}
}
Accessible.role: Accessible.EditableText
Accessible.name: contextLengthLabel.text
Accessible.description: ToolTip.text
}
}
MySettingsLabel {
id: tempLabel
text: qsTr("Temperature")
helpText: qsTr("Randomness of model output. Higher -> more variation.")
Layout.row: 1
Layout.column: 2
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: temperatureField
text: root.currentModelInfo.temperature
font.pixelSize: theme.fontSizeLarge
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: 1
Layout.column: 3
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
}
MySettingsLabel {
id: topPLabel
text: qsTr("Top-P")
helpText: qsTr("Nucleus Sampling factor. Lower -> more predictable.")
Layout.row: 2
Layout.column: 0
Layout.maximumWidth: 300 * theme.fontScale
}
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.")
ToolTip.visible: hovered
Layout.row: 2
Layout.column: 1
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
}
MySettingsLabel {
id: minPLabel
text: qsTr("Min-P")
helpText: qsTr("Minimum token probability. Higher -> more predictable.")
Layout.row: 3
Layout.column: 0
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: minPField
text: root.currentModelInfo.minP
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Sets the minimum relative probability for a token to be considered.")
ToolTip.visible: hovered
Layout.row: 3
Layout.column: 1
validator: DoubleValidator {
locale: "C"
}
Connections {
target: MySettings
function onMinPChanged() {
minPField.text = root.currentModelInfo.minP;
}
}
Connections {
target: root
function onCurrentModelInfoChanged() {
minPField.text = root.currentModelInfo.minP;
}
}
onEditingFinished: {
var val = parseFloat(text)
if (!isNaN(val)) {
MySettings.setModelMinP(root.currentModelInfo, val)
focus = false
} else {
text = root.currentModelInfo.minP
}
}
Accessible.role: Accessible.EditableText
Accessible.name: minPLabel.text
Accessible.description: ToolTip.text
}
MySettingsLabel {
id: topKLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Top-K")
helpText: qsTr("Size of selection pool for tokens.")
Layout.row: 2
Layout.column: 2
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: topKField
visible: !root.currentModelInfo.isOnline
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: 2
Layout.column: 3
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
}
MySettingsLabel {
id: maxLengthLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Max Length")
helpText: qsTr("Maximum response length, in tokens.")
Layout.row: 0
Layout.column: 2
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: maxLengthField
visible: !root.currentModelInfo.isOnline
text: root.currentModelInfo.maxLength
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
Layout.row: 0
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
}
MySettingsLabel {
id: batchSizeLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Prompt Batch Size")
helpText: qsTr("The batch size used for prompt processing.")
Layout.row: 1
Layout.column: 0
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: batchSizeField
visible: !root.currentModelInfo.isOnline
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: 1
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
}
MySettingsLabel {
id: repeatPenaltyLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Repeat Penalty")
helpText: qsTr("Repetition penalty factor. Set to 1 to disable.")
Layout.row: 4
Layout.column: 2
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: repeatPenaltyField
visible: !root.currentModelInfo.isOnline
text: root.currentModelInfo.repeatPenalty
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
Layout.row: 4
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
}
MySettingsLabel {
id: repeatPenaltyTokensLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Repeat Penalty Tokens")
helpText: qsTr("Number of previous tokens used for penalty.")
Layout.row: 3
Layout.column: 2
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: repeatPenaltyTokenField
visible: !root.currentModelInfo.isOnline
text: root.currentModelInfo.repeatPenaltyTokens
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
Layout.row: 3
Layout.column: 3
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
}
MySettingsLabel {
id: gpuLayersLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("GPU Layers")
helpText: qsTr("Number of model layers to load into VRAM.")
Layout.row: 4
Layout.column: 0
Layout.maximumWidth: 300 * theme.fontScale
}
MyTextField {
id: gpuLayersField
visible: !root.currentModelInfo.isOnline
text: root.currentModelInfo.gpuLayers
font.pixelSize: theme.fontSizeLarge
color: theme.textColor
ToolTip.text: qsTr("How many model layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
ToolTip.visible: hovered
Layout.row: 4
Layout.column: 1
Connections {
target: MySettings
function onGpuLayersChanged() {
gpuLayersField.text = root.currentModelInfo.gpuLayers
}
}
Connections {
target: root
function onCurrentModelInfoChanged() {
if (root.currentModelInfo.gpuLayers === 100) {
gpuLayersField.text = root.currentModelInfo.maxGpuLayers
} else {
gpuLayersField.text = root.currentModelInfo.gpuLayers
}
}
}
onEditingFinished: {
var val = parseInt(text)
if (isNaN(val)) {
gpuLayersField.text = root.currentModelInfo.gpuLayers
} else {
if (val < 1) {
val = 1
gpuLayersField.text = val
} else if (val > root.currentModelInfo.maxGpuLayers) {
val = root.currentModelInfo.maxGpuLayers
gpuLayersField.text = val
}
MySettings.setModelGpuLayers(root.currentModelInfo, val)
focus = false
}
}
Accessible.role: Accessible.EditableText
Accessible.name: gpuLayersLabel.text
Accessible.description: ToolTip.text
}
}
Rectangle {
Layout.row: 16
Layout.column: 0
Layout.columnSpan: 2
Layout.topMargin: 15
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
}
}
}