mirror of
				https://github.com/nomic-ai/gpt4all.git
				synced 2025-10-31 05:41:39 +00:00 
			
		
		
		
	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>
		
			
				
	
	
		
			1000 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			QML
		
	
	
	
	
	
			
		
		
	
	
			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
 | |
|         }
 | |
|     }
 | |
| }
 |