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:
Adam Treat
2023-07-01 11:34:21 -04:00
committed by AT
parent 2a6c673c25
commit 6d9cdf228c
30 changed files with 2041 additions and 881 deletions

View File

@@ -6,8 +6,12 @@ import QtQuick.Layouts
import QtQuick.Dialogs
import modellist
import mysettings
import network
MySettingsTab {
onRestoreDefaultsClicked: {
MySettings.restoreApplicationDefaults();
}
title: qsTr("Application")
contentItem: GridLayout {
id: applicationSettingsTabInner
@@ -26,7 +30,9 @@ MySettingsTab {
id: comboBox
Layout.row: 1
Layout.column: 1
Layout.columnSpan: 2
Layout.minimumWidth: 350
Layout.fillWidth: true
model: ModelList.userDefaultModelList
Accessible.role: Accessible.ComboBox
Accessible.name: qsTr("ComboBox for displaying/picking the default model")
@@ -178,25 +184,30 @@ MySettingsTab {
Layout.columnSpan: 3
Layout.fillWidth: true
height: 1
color: theme.dialogBorder
color: theme.tabBorder
}
}
advancedSettings: GridLayout {
columns: 3
rowSpacing: 10
columnSpacing: 10
Rectangle {
Layout.row: 9
Layout.row: 2
Layout.column: 0
Layout.fillWidth: true
Layout.columnSpan: 3
height: 1
color: theme.dialogBorder
color: theme.tabBorder
}
Label {
id: gpuOverrideLabel
text: qsTr("Force Metal (macOS+arm):")
color: theme.textColor
Layout.row: 8
Layout.row: 1
Layout.column: 0
}
RowLayout {
Layout.row: 8
Layout.row: 1
Layout.column: 1
Layout.columnSpan: 2
MyCheckBox {
@@ -206,24 +217,18 @@ MySettingsTab {
MySettings.forceMetal = !MySettings.forceMetal
}
}
Label {
id: warningLabel
Layout.maximumWidth: 730
Item {
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
color: theme.textErrorColor
wrapMode: Text.WordWrap
text: qsTr("WARNING: On macOS with arm (M1+) this setting forces usage of the GPU. Can cause crashes if the model requires more RAM than the system supports. Because of crash possibility the setting will not persist across restarts of the application. This has no effect on non-macs or intel.")
}
}
MyButton {
Layout.row: 10
Layout.column: 1
Layout.columnSpan: 2
Layout.fillWidth: true
text: qsTr("Restore Defaults")
Accessible.description: qsTr("Restores the settings dialog to a default state")
onClicked: {
MySettings.restoreApplicationDefaults();
Layout.minimumHeight: warningLabel.height
Label {
id: warningLabel
width: parent.width
color: theme.textErrorColor
wrapMode: Text.WordWrap
text: qsTr("WARNING: On macOS with arm (M1+) this setting forces usage of the GPU. Can cause crashes if the model requires more RAM than the system supports. Because of crash possibility the setting will not persist across restarts of the application. This has no effect on non-macs or intel.")
}
}
}
}

View File

@@ -1,302 +0,0 @@
import QtCore
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Layouts
import localdocs
import mysettings
MySettingsTab {
title: qsTr("Presets")
contentItem: GridLayout {
id: generationSettingsTabInner
columns: 2
rowSpacing: 10
columnSpacing: 10
Label {
id: tempLabel
text: qsTr("Temperature:")
color: theme.textColor
Layout.row: 0
Layout.column: 0
}
MyTextField {
text: MySettings.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"
}
onEditingFinished: {
var val = parseFloat(text)
if (!isNaN(val)) {
MySettings.temperature = val
focus = false
} else {
text = MySettings.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: 1
Layout.column: 0
}
MyTextField {
text: MySettings.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: 1
Layout.column: 1
validator: DoubleValidator {
locale: "C"
}
onEditingFinished: {
var val = parseFloat(text)
if (!isNaN(val)) {
MySettings.topP = val
focus = false
} else {
text = MySettings.topP
}
}
Accessible.role: Accessible.EditableText
Accessible.name: topPLabel.text
Accessible.description: ToolTip.text
}
Label {
id: topKLabel
text: qsTr("Top K:")
color: theme.textColor
Layout.row: 2
Layout.column: 0
}
MyTextField {
text: MySettings.topK
color: theme.textColor
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from")
ToolTip.visible: hovered
Layout.row: 2
Layout.column: 1
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.topK = val
focus = false
} else {
text = MySettings.topK
}
}
Accessible.role: Accessible.EditableText
Accessible.name: topKLabel.text
Accessible.description: ToolTip.text
}
Label {
id: maxLengthLabel
text: qsTr("Max Length:")
color: theme.textColor
Layout.row: 3
Layout.column: 0
}
MyTextField {
text: MySettings.maxLength
color: theme.textColor
ToolTip.text: qsTr("Maximum length of response in tokens")
ToolTip.visible: hovered
Layout.row: 3
Layout.column: 1
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.maxLength = val
focus = false
} else {
text = MySettings.maxLength
}
}
Accessible.role: Accessible.EditableText
Accessible.name: maxLengthLabel.text
Accessible.description: ToolTip.text
}
Label {
id: batchSizeLabel
text: qsTr("Prompt Batch Size:")
color: theme.textColor
Layout.row: 4
Layout.column: 0
}
MyTextField {
text: MySettings.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: 4
Layout.column: 1
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.promptBatchSize = val
focus = false
} else {
text = MySettings.promptBatchSize
}
}
Accessible.role: Accessible.EditableText
Accessible.name: batchSizeLabel.text
Accessible.description: ToolTip.text
}
Label {
id: repeatPenaltyLabel
text: qsTr("Repeat Penalty:")
color: theme.textColor
Layout.row: 5
Layout.column: 0
}
MyTextField {
text: MySettings.repeatPenalty
color: theme.textColor
ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
ToolTip.visible: hovered
Layout.row: 5
Layout.column: 1
validator: DoubleValidator {
locale: "C"
}
onEditingFinished: {
var val = parseFloat(text)
if (!isNaN(val)) {
MySettings.repeatPenalty = val
focus = false
} else {
text = MySettings.repeatPenalty
}
}
Accessible.role: Accessible.EditableText
Accessible.name: repeatPenaltyLabel.text
Accessible.description: ToolTip.text
}
Label {
id: repeatPenaltyTokensLabel
text: qsTr("Repeat Penalty Tokens:")
color: theme.textColor
Layout.row: 6
Layout.column: 0
}
MyTextField {
text: MySettings.repeatPenaltyTokens
color: theme.textColor
ToolTip.text: qsTr("How far back in output to apply repeat penalty")
ToolTip.visible: hovered
Layout.row: 6
Layout.column: 1
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.repeatPenaltyTokens = val
focus = false
} else {
text = MySettings.repeatPenaltyTokens
}
}
Accessible.role: Accessible.EditableText
Accessible.name: repeatPenaltyTokensLabel.text
Accessible.description: ToolTip.text
}
ColumnLayout {
Layout.row: 7
Layout.column: 0
Layout.topMargin: 10
Layout.alignment: Qt.AlignTop
spacing: 20
Label {
id: promptTemplateLabel
text: qsTr("Prompt Template:")
color: theme.textColor
}
Label {
id: promptTemplateLabelHelp
Layout.maximumWidth: promptTemplateLabel.width
visible: templateTextArea.text.indexOf(
"%1") === -1
color: theme.textErrorColor
text: qsTr("Must contain the string \"%1\" to be replaced with the user's input.")
wrapMode: TextArea.Wrap
Accessible.role: Accessible.EditableText
Accessible.name: text
}
}
Rectangle {
Layout.row: 7
Layout.column: 1
Layout.fillWidth: true
height: 200
color: "transparent"
clip: true
ScrollView {
id: templateScrollView
anchors.fill: parent
TextArea {
id: templateTextArea
text: MySettings.promptTemplate
color: theme.textColor
background: Rectangle {
implicitWidth: 150
color: theme.backgroundLighter
radius: 10
}
padding: 10
wrapMode: TextArea.Wrap
onTextChanged: {
if (templateTextArea.text.indexOf("%1") !== -1) {
MySettings.promptTemplate = 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
}
}
}
MyButton {
Layout.row: 8
Layout.column: 1
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
}
}
}
}

View File

@@ -6,8 +6,13 @@ import QtQuick.Layouts
import QtQuick.Dialogs
import localdocs
import mysettings
import network
MySettingsTab {
onRestoreDefaultsClicked: {
MySettings.restoreLocalDocsDefaults();
}
title: qsTr("LocalDocs Plugin (BETA)")
contentItem: ColumnLayout {
id: root
@@ -25,101 +30,95 @@ MySettingsTab {
}
}
RowLayout {
Item {
Layout.fillWidth: true
height: collection.height + 20
spacing: 10
MyTextField {
id: collection
width: 225
horizontalAlignment: Text.AlignJustify
color: theme.textColor
placeholderText: qsTr("Collection name...")
placeholderTextColor: theme.mutedTextColor
ToolTip.text: qsTr("Name of the collection to add (Required)")
ToolTip.visible: hovered
Accessible.role: Accessible.EditableText
Accessible.name: collection.text
Accessible.description: ToolTip.text
function showError() {
collection.placeholderTextColor = theme.textErrorColor
}
onTextChanged: {
collection.placeholderTextColor = theme.mutedTextColor
}
}
MyDirectoryField {
id: folderEdit
Layout.fillWidth: true
text: root.folder_path
placeholderText: qsTr("Folder path...")
placeholderTextColor: theme.mutedTextColor
ToolTip.text: qsTr("Folder path to documents (Required)")
ToolTip.visible: hovered
function showError() {
folderEdit.placeholderTextColor = theme.textErrorColor
}
onTextChanged: {
folderEdit.placeholderTextColor = theme.mutedTextColor
}
}
MyButton {
id: browseButton
text: qsTr("Browse")
onClicked: {
folderDialog.open();
}
}
MyButton {
id: addButton
text: qsTr("Add")
Accessible.role: Accessible.Button
Accessible.name: text
Accessible.description: qsTr("Add button")
onClicked: {
var isError = false;
if (root.collection === "") {
isError = true;
collection.showError();
height: row.height
RowLayout {
id: row
anchors.left: parent.left
anchors.right: parent.right
height: collection.height
spacing: 10
MyTextField {
id: collection
width: 225
horizontalAlignment: Text.AlignJustify
color: theme.textColor
placeholderText: qsTr("Collection name...")
placeholderTextColor: theme.mutedTextColor
ToolTip.text: qsTr("Name of the collection to add (Required)")
ToolTip.visible: hovered
Accessible.role: Accessible.EditableText
Accessible.name: collection.text
Accessible.description: ToolTip.text
function showError() {
collection.placeholderTextColor = theme.textErrorColor
}
if (root.folder_path === "" || !folderEdit.isValid) {
isError = true;
folderEdit.showError();
onTextChanged: {
collection.placeholderTextColor = theme.mutedTextColor
}
}
MyDirectoryField {
id: folderEdit
Layout.fillWidth: true
text: root.folder_path
placeholderText: qsTr("Folder path...")
placeholderTextColor: theme.mutedTextColor
ToolTip.text: qsTr("Folder path to documents (Required)")
ToolTip.visible: hovered
function showError() {
folderEdit.placeholderTextColor = theme.textErrorColor
}
onTextChanged: {
folderEdit.placeholderTextColor = theme.mutedTextColor
}
}
MyButton {
id: browseButton
text: qsTr("Browse")
onClicked: {
folderDialog.open();
}
}
MyButton {
id: addButton
text: qsTr("Add")
Accessible.role: Accessible.Button
Accessible.name: text
Accessible.description: qsTr("Add button")
onClicked: {
var isError = false;
if (root.collection === "") {
isError = true;
collection.showError();
}
if (root.folder_path === "" || !folderEdit.isValid) {
isError = true;
folderEdit.showError();
}
if (isError)
return;
LocalDocs.addFolder(root.collection, root.folder_path)
root.collection = ""
root.folder_path = ""
collection.clear()
}
if (isError)
return;
LocalDocs.addFolder(root.collection, root.folder_path)
root.collection = ""
root.folder_path = ""
collection.clear()
}
}
}
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.bottomMargin: 10
clip: true
contentHeight: 300
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
background: Rectangle {
color: theme.backgroundLighter
}
ListView {
id: listView
ColumnLayout {
spacing: 0
Repeater {
model: LocalDocs.localDocsModel
boundsBehavior: Flickable.StopAtBounds
delegate: Rectangle {
id: item
width: listView.width
Layout.fillWidth: true
height: buttons.height + 20
color: index % 2 === 0 ? theme.backgroundLight : theme.backgroundLighter
color: index % 2 === 0 ? theme.backgroundDark : theme.backgroundDarker
property bool removing: false
Text {
@@ -136,6 +135,7 @@ MySettingsTab {
Text {
id: folderId
anchors.left: collectionId.right
anchors.right: buttons.left
anchors.margins: 20
anchors.verticalCenter: parent.verticalCenter
text: folder_path
@@ -170,124 +170,99 @@ MySettingsTab {
}
}
GridLayout {
id: gridLayout
Rectangle {
Layout.fillWidth: true
columns: 3
rowSpacing: 10
columnSpacing: 10
height: 1
color: theme.tabBorder
}
}
advancedSettings: GridLayout {
id: gridLayout
columns: 3
rowSpacing: 10
columnSpacing: 10
Rectangle {
Layout.row: 0
Layout.column: 0
Layout.fillWidth: true
Layout.columnSpan: 3
height: 1
color: theme.dialogBorder
Rectangle {
Layout.row: 3
Layout.column: 0
Layout.fillWidth: true
Layout.columnSpan: 3
height: 1
color: theme.tabBorder
}
Label {
id: chunkLabel
Layout.row: 1
Layout.column: 0
color: theme.textColor
text: qsTr("Document snippet size (characters):")
}
MyTextField {
id: chunkSizeTextField
Layout.row: 1
Layout.column: 1
ToolTip.text: qsTr("Number of characters per document snippet.\nNOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.visible: hovered
text: MySettings.localDocsChunkSize
validator: IntValidator {
bottom: 1
}
Rectangle {
Layout.row: 3
Layout.column: 0
Layout.fillWidth: true
Layout.columnSpan: 3
height: 1
color: theme.dialogBorder
}
// This is here just to stretch out the third column
Rectangle {
Layout.row: 3
Layout.column: 2
Layout.fillWidth: true
height: 1
color: theme.dialogBorder
}
Label {
id: chunkLabel
Layout.row: 1
Layout.column: 0
color: theme.textColor
text: qsTr("Document snippet size (characters):")
}
MyTextField {
id: chunkSizeTextField
Layout.row: 1
Layout.column: 1
ToolTip.text: qsTr("Number of characters per document snippet.\nNOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.visible: hovered
text: MySettings.localDocsChunkSize
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.localDocsChunkSize = val
focus = false
} else {
text = MySettings.localDocsChunkSize
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.localDocsChunkSize = val
focus = false
} else {
text = MySettings.localDocsChunkSize
}
}
}
Label {
id: contextItemsPerPrompt
Layout.row: 2
Layout.column: 0
color: theme.textColor
text: qsTr("Document snippets per prompt:")
Label {
id: contextItemsPerPrompt
Layout.row: 2
Layout.column: 0
color: theme.textColor
text: qsTr("Document snippets per prompt:")
}
MyTextField {
Layout.row: 2
Layout.column: 1
ToolTip.text: qsTr("Best N matches of retrieved document snippets to add to the context for prompt.\nNOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.visible: hovered
text: MySettings.localDocsRetrievalSize
validator: IntValidator {
bottom: 1
}
MyTextField {
Layout.row: 2
Layout.column: 1
ToolTip.text: qsTr("Best N matches of retrieved document snippets to add to the context for prompt.\nNOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.visible: hovered
text: MySettings.localDocsRetrievalSize
validator: IntValidator {
bottom: 1
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.localDocsRetrievalSize = val
focus = false
} else {
text = MySettings.localDocsRetrievalSize
}
onEditingFinished: {
var val = parseInt(text)
if (!isNaN(val)) {
MySettings.localDocsRetrievalSize = val
focus = false
} else {
text = MySettings.localDocsRetrievalSize
}
}
}
Item {
Layout.row: 1
Layout.column: 2
Layout.rowSpan: 2
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
Layout.minimumHeight: warningLabel.height
Label {
id: warningLabel
Layout.row: 1
Layout.column: 2
Layout.rowSpan: 2
Layout.maximumWidth: 520
Layout.alignment: Qt.AlignTop
width: parent.width
color: theme.textErrorColor
wrapMode: Text.WordWrap
text: qsTr("Warning: Advanced usage only. Values too large may cause localdocs failure, extremely slow responses or failure to respond at all. Roughly speaking, the {N chars x N snippets} are added to the model's context window. More info <a href=\"https://docs.gpt4all.io/gpt4all_chat.html#localdocs-beta-plugin-chat-with-your-data\">here.</a>")
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
}
MyButton {
id: restoreDefaultsButton
Layout.row: 4
Layout.column: 1
Layout.columnSpan: 2
Layout.fillWidth: true
text: qsTr("Restore Defaults")
Accessible.role: Accessible.Button
Accessible.name: text
Accessible.description: qsTr("Restores the settings dialog to a default state")
onClicked: {
MySettings.restoreLocalDocsDefaults();
}
}
}
}
}

View File

@@ -83,7 +83,7 @@ Dialog {
Text {
textFormat: Text.StyledText
text: "<h2>" + (name !== "" ? name : filename) + "</h2>"
text: "<h2>" + name + "</h2>"
Layout.row: 0
Layout.column: 0
Layout.topMargin: 20
@@ -329,12 +329,14 @@ Dialog {
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: 150
Layout.maximumWidth: textMetrics.width + 25
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
color: theme.textColor
background: Rectangle {
color: theme.backgroundLighter
radius: 10
}
wrapMode: Text.WrapAnywhere
function showError() {
openaiKey.placeholderTextColor = theme.textErrorColor
}
@@ -346,6 +348,11 @@ Dialog {
Accessible.role: Accessible.EditableText
Accessible.name: placeholderText
Accessible.description: qsTr("Whether the file hash is being calculated")
TextMetrics {
id: textMetrics
font: openaiKey.font
text: openaiKey.placeholderText
}
}
}
}

View File

@@ -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
}
}
}

View File

@@ -17,7 +17,7 @@ Button {
border.color: myButton.down ? theme.backgroundLightest : theme.buttonBorder
border.width: 2
radius: 10
color: myButton.hovered ? theme.backgroundLighter : theme.backgroundLight
color: myButton.hovered ? theme.backgroundDark : theme.backgroundDarkest
}
Accessible.role: Accessible.Button
Accessible.name: text

View File

@@ -9,14 +9,13 @@ ComboBox {
padding: 10
Accessible.role: Accessible.ComboBox
contentItem: Text {
anchors.horizontalCenter: parent.horizontalCenter
id: text
leftPadding: 10
rightPadding: 20
text: comboBox.displayText
font: comboBox.font
color: theme.textColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
delegate: ItemDelegate {

View File

@@ -11,7 +11,7 @@ TextField {
color: text === "" || isValid ? theme.textColor : theme.textErrorColor
background: Rectangle {
implicitWidth: 150
color: theme.backgroundLighter
color: theme.backgroundDark
radius: 10
}
}

View File

@@ -12,71 +12,56 @@ Item {
id: theme
}
property alias title: titleLabel.text
property ListModel tabTitlesModel: ListModel { }
property list<Component> tabs: [ ]
Canvas {
id: canvas
anchors.fill: parent
contextType: "2d"
onPaint: {
var context = getContext("2d");
context.reset();
context.lineWidth = 2;
context.moveTo(stackLayout.x, stackLayout.y);
context.lineTo(stackLayout.x, stackLayout.y + stackLayout.height);
context.lineTo(stackLayout.x + stackLayout.width, stackLayout.y + stackLayout.height);
context.lineTo(stackLayout.x + stackLayout.width, stackLayout.y);
context.lineTo(/*settingsTabBar.currentItem.x + */settingsTabBar.currentItem.width, stackLayout.y);
context.strokeStyle = theme.tabBorder;
context.stroke();
}
Label {
id: titleLabel
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
color: theme.textColor
padding: 10
font.bold: true
font.pixelSize: theme.fontSizeLarger
}
Rectangle {
anchors.top: titleLabel.bottom
anchors.leftMargin: 15
anchors.rightMargin: 15
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: theme.tabBorder
}
TabBar {
id: settingsTabBar
width: parent.width / 1.25
anchors.top: titleLabel.bottom
anchors.topMargin: 15
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width / 1.75
z: 200
visible: tabTitlesModel.count > 1
background: Rectangle {
color: "transparent"
}
Repeater {
model: settingsStack.tabTitlesModel
TabButton {
id: tabButton
padding: 10
contentItem: IconLabel {
color: theme.textColor
font.bold: tabButton.checked
text: model.title
}
background: Rectangle {
color: tabButton.checked ? theme.backgroundDarkest : theme.backgroundLight
// Rectangle {
// anchors.top: parent.top
// anchors.left: parent.left
// anchors.right: parent.right
// height: tabButton.checked
// color: theme.tabBorder
// }
// Rectangle {
// anchors.bottom: parent.bottom
// anchors.left: parent.left
// anchors.right: parent.right
// height: !tabButton.checked
// color: theme.tabBorder
// }
// Rectangle {
// anchors.top: parent.top
// anchors.bottom: parent.bottom
// anchors.left: parent.left
// width: tabButton.checked
// color: theme.tabBorder
// }
// Rectangle {
// anchors.top: parent.top
// anchors.bottom: parent.bottom
// anchors.right: parent.right
// width: tabButton.checked
// color: theme.tabBorder
// }
color: "transparent"
border.width: 1
border.color: tabButton.checked ? theme.tabBorder : "transparent"
radius: 10
}
Accessible.role: Accessible.Button
Accessible.name: model.title
@@ -84,9 +69,31 @@ Item {
}
}
Rectangle {
id: dividerTabBar
visible: tabTitlesModel.count > 1
anchors.top: settingsTabBar.bottom
anchors.topMargin: 15
anchors.bottomMargin: 15
anchors.leftMargin: 15
anchors.rightMargin: 15
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: theme.tabBorder
}
Rectangle {
anchors.fill: parent
color: "transparent"
radius: 10
border.width: 1
border.color: theme.tabBorder
}
StackLayout {
id: stackLayout
anchors.top: tabTitlesModel.count > 1 ? settingsTabBar.bottom : parent.top
anchors.top: tabTitlesModel.count > 1 ? dividerTabBar.bottom : titleLabel.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom

View File

@@ -5,42 +5,87 @@ import QtQuick.Controls.Basic
import QtQuick.Layouts
Item {
id: root
property string title: ""
property Item contentItem: null
property Item advancedSettings: null
signal restoreDefaultsClicked
onContentItemChanged: function() {
if (contentItem) {
contentItem.parent = tabInner;
contentItem.anchors.left = tabInner.left;
contentItem.anchors.right = tabInner.right;
contentItem.parent = contentInner;
contentItem.anchors.left = contentInner.left;
contentItem.anchors.right = contentInner.right;
}
}
onAdvancedSettingsChanged: function() {
if (advancedSettings) {
advancedSettings.parent = advancedInner;
advancedSettings.anchors.left = advancedInner.left;
advancedSettings.anchors.right = advancedInner.right;
}
}
ScrollView {
id: root
width: parent.width
height: parent.height
padding: 15
rightPadding: 20
contentWidth: availableWidth
contentHeight: tabInner.height
contentHeight: innerColumn.height
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
Theme {
id: theme
}
// background: Rectangle {
// color: 'transparent'
// border.color: theme.tabBorder
// border.width: 1
// radius: 10
// }
Column {
id: tabInner
ColumnLayout {
id: innerColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 15
spacing: 10
Column {
id: contentInner
Layout.fillWidth: true
}
Column {
id: advancedInner
visible: false
Layout.fillWidth: true
}
Item {
Layout.fillWidth: true
height: restoreDefaultsButton.height
MyButton {
id: restoreDefaultsButton
anchors.left: parent.left
width: implicitWidth
text: qsTr("Restore Defaults")
Accessible.role: Accessible.Button
Accessible.name: text
Accessible.description: qsTr("Restores the settings dialog to a default state")
onClicked: {
root.restoreDefaultsClicked();
}
}
MyButton {
id: advancedSettingsButton
anchors.right: parent.right
visible: root.advancedSettings
width: implicitWidth
text: !advancedInner.visible ? qsTr("Advanced Settings") : qsTr("Hide Advanced Settings")
Accessible.role: Accessible.Button
Accessible.name: text
Accessible.description: qsTr("Shows/hides the advanced settings")
onClicked: {
advancedInner.visible = !advancedInner.visible;
}
}
}
}
}
}

View File

@@ -8,7 +8,7 @@ TextField {
padding: 10
background: Rectangle {
implicitWidth: 150
color: theme.backgroundLighter
color: theme.backgroundDark
radius: 10
}
}

View File

@@ -14,7 +14,6 @@ import mysettings
Dialog {
id: settingsDialog
modal: true
opacity: 0.9
padding: 20
bottomPadding: 30
background: Rectangle {
@@ -38,7 +37,7 @@ Dialog {
ListModel {
id: stacksModel
ListElement {
title: "Generation"
title: "Models"
}
ListElement {
title: "Application"
@@ -67,7 +66,6 @@ Dialog {
id: item
width: listView.width
height: titleLabel.height + 25
// color: index % 2 === 0 ? theme.backgroundLight : theme.backgroundLighter
color: "transparent"
border.color: theme.backgroundLighter
border.width: index == listView.currentIndex ? 1 : 0
@@ -78,6 +76,7 @@ Dialog {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.margins: 20
font.bold: index == listView.currentIndex
text: title
elide: Text.ElideRight
color: theme.textColor
@@ -101,19 +100,21 @@ Dialog {
currentIndex: listView.currentIndex
MySettingsStack {
title: qsTr("Model/Character Settings")
tabs: [
Component { ModelSettings { } },
Component { GenerationSettings { } }
Component { ModelSettings { } }
]
}
MySettingsStack {
title: qsTr("Application General Settings")
tabs: [
Component { ApplicationSettings { } }
]
}
MySettingsStack {
title: qsTr("LocalDocs Plugin (BETA) Settings")
tabs: [
Component { LocalDocsSettings { } }
]

View File

@@ -7,9 +7,9 @@ QtObject {
property color textAccent: "#8e8ea0"
property color mutedTextColor: backgroundLightest
property color textErrorColor: "red"
property color backgroundDarkest: "#202123"
property color backgroundDarker: "#222326"
property color backgroundDark: "#242528"
property color backgroundDarkest: "#1c1f21"
property color backgroundDarker: "#1e2123"
property color backgroundDark: "#222527"
property color backgroundLight: "#343541"
property color backgroundLighter: "#444654"
property color backgroundLightest: "#7d7d8e"