mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-09-25 06:44:29 +00:00
Moving everything to subdir for monorepo merge.
This commit is contained in:
113
gpt4all-chat/qml/AboutDialog.qml
Normal file
113
gpt4all-chat/qml/AboutDialog.qml
Normal file
@@ -0,0 +1,113 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: abpoutDialog
|
||||
anchors.centerIn: parent
|
||||
modal: false
|
||||
opacity: 0.9
|
||||
padding: 20
|
||||
width: 1024
|
||||
height: column.height + 40
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
spacing: 20
|
||||
Item {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
Image {
|
||||
id: img
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 60
|
||||
height: 60
|
||||
source: "qrc:/gpt4all/icons/logo.svg"
|
||||
}
|
||||
Text {
|
||||
anchors.left: img.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.verticalCenter: img.verticalCenter
|
||||
text: qsTr("About GPT4All")
|
||||
color: theme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
clip: true
|
||||
height: 200
|
||||
width: 1024 - 40
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
TextArea {
|
||||
id: welcome
|
||||
wrapMode: Text.Wrap
|
||||
width: 1024 - 40
|
||||
padding: 20
|
||||
textFormat: TextEdit.MarkdownText
|
||||
text: qsTr("### Release notes\n")
|
||||
+ Download.releaseInfo.notes
|
||||
+ qsTr("### Contributors\n")
|
||||
+ Download.releaseInfo.contributors
|
||||
color: theme.textColor
|
||||
focus: false
|
||||
readOnly: true
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Release notes")
|
||||
Accessible.description: qsTr("Release notes for this version")
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLight
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: discordLink
|
||||
width: parent.width
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("Check out our discord channel <a href=\"https://discord.gg/4M2QFmTt2k\">https://discord.gg/4M2QFmTt2k</a>")
|
||||
onLinkActivated: { Qt.openUrlExternally("https://discord.gg/4M2QFmTt2k") }
|
||||
color: theme.textColor
|
||||
linkColor: theme.linkColor
|
||||
|
||||
Accessible.role: Accessible.Link
|
||||
Accessible.name: qsTr("Discord link")
|
||||
}
|
||||
|
||||
Label {
|
||||
id: nomicProps
|
||||
width: parent.width
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
text: qsTr("Thank you to <a href=\"https://home.nomic.ai\">Nomic AI</a> and the community for contributing so much great data, code, ideas, and energy to the growing open source AI ecosystem!")
|
||||
onLinkActivated: { Qt.openUrlExternally("https://home.nomic.ai") }
|
||||
color: theme.textColor
|
||||
linkColor: theme.linkColor
|
||||
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Thank you blurb")
|
||||
Accessible.description: qsTr("Contains embedded link to https://home.nomic.ai")
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
}
|
353
gpt4all-chat/qml/ChatDrawer.qml
Normal file
353
gpt4all-chat/qml/ChatDrawer.qml
Normal file
@@ -0,0 +1,353 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import llm
|
||||
import download
|
||||
import network
|
||||
|
||||
Drawer {
|
||||
id: chatDrawer
|
||||
modal: false
|
||||
opacity: 0.9
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
signal downloadClicked
|
||||
signal aboutClicked
|
||||
|
||||
background: Rectangle {
|
||||
height: parent.height
|
||||
color: theme.backgroundDarkest
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
|
||||
Accessible.role: Accessible.Pane
|
||||
Accessible.name: qsTr("Drawer on the left of the application")
|
||||
Accessible.description: qsTr("Drawer that is revealed by pressing the hamburger button")
|
||||
|
||||
Button {
|
||||
id: newChat
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
padding: 15
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
background: Rectangle {
|
||||
color: theme.backgroundDarkest
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
}
|
||||
contentItem: Text {
|
||||
text: qsTr("New chat")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Use this to launch an external application that will check for updates to the installer")
|
||||
}
|
||||
onClicked: {
|
||||
LLM.chatListModel.addChat();
|
||||
Network.sendNewChat(LLM.chatListModel.count)
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: -10
|
||||
anchors.topMargin: 10
|
||||
anchors.top: newChat.bottom
|
||||
anchors.bottom: checkForUpdatesButton.top
|
||||
anchors.bottomMargin: 10
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
|
||||
ListView {
|
||||
id: conversationList
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 10
|
||||
|
||||
model: LLM.chatListModel
|
||||
|
||||
delegate: Rectangle {
|
||||
id: chatRectangle
|
||||
width: conversationList.width
|
||||
height: chatName.height
|
||||
opacity: 0.9
|
||||
property bool isCurrent: LLM.chatListModel.currentChat === LLM.chatListModel.get(index)
|
||||
property bool trashQuestionDisplayed: false
|
||||
z: isCurrent ? 199 : 1
|
||||
color: index % 2 === 0 ? theme.backgroundLight : theme.backgroundLighter
|
||||
border.width: isCurrent
|
||||
border.color: chatName.readOnly ? theme.assistantColor : theme.userColor
|
||||
TextField {
|
||||
id: chatName
|
||||
anchors.left: parent.left
|
||||
anchors.right: buttons.left
|
||||
color: theme.textColor
|
||||
padding: 15
|
||||
focus: false
|
||||
readOnly: true
|
||||
wrapMode: Text.NoWrap
|
||||
hoverEnabled: false // Disable hover events on the TextArea
|
||||
selectByMouse: false // Disable text selection in the TextArea
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
text: readOnly ? metrics.elidedText : name
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
opacity: trashQuestionDisplayed ? 0.5 : 1.0
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
font: chatName.font
|
||||
text: name
|
||||
elide: Text.ElideRight
|
||||
elideWidth: chatName.width - 25
|
||||
}
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
onEditingFinished: {
|
||||
// Work around a bug in qml where we're losing focus when the whole window
|
||||
// goes out of focus even though this textfield should be marked as not
|
||||
// having focus
|
||||
if (chatName.readOnly)
|
||||
return;
|
||||
changeName();
|
||||
Network.sendRenameChat()
|
||||
}
|
||||
function changeName() {
|
||||
LLM.chatListModel.get(index).name = chatName.text
|
||||
chatName.focus = false
|
||||
chatName.readOnly = true
|
||||
chatName.selectByMouse = false
|
||||
}
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
if (isCurrent)
|
||||
return;
|
||||
LLM.chatListModel.currentChat = LLM.chatListModel.get(index);
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Select the current chat")
|
||||
Accessible.description: qsTr("Provides a button to select the current chat or edit the chat when in edit mode")
|
||||
}
|
||||
Row {
|
||||
id: buttons
|
||||
anchors.verticalCenter: chatName.verticalCenter
|
||||
anchors.right: chatRectangle.right
|
||||
anchors.rightMargin: 10
|
||||
spacing: 10
|
||||
Button {
|
||||
id: editButton
|
||||
width: 30
|
||||
height: 30
|
||||
visible: isCurrent
|
||||
opacity: trashQuestionDisplayed ? 0.5 : 1.0
|
||||
background: Image {
|
||||
width: 30
|
||||
height: 30
|
||||
source: "qrc:/gpt4all/icons/edit.svg"
|
||||
}
|
||||
onClicked: {
|
||||
chatName.focus = true
|
||||
chatName.readOnly = false
|
||||
chatName.selectByMouse = true
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Edit the chat name")
|
||||
Accessible.description: qsTr("Provides a button to edit the chat name")
|
||||
}
|
||||
Button {
|
||||
id: c
|
||||
width: 30
|
||||
height: 30
|
||||
visible: isCurrent
|
||||
background: Image {
|
||||
width: 30
|
||||
height: 30
|
||||
source: "qrc:/gpt4all/icons/trash.svg"
|
||||
}
|
||||
onClicked: {
|
||||
trashQuestionDisplayed = true
|
||||
timer.start()
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Delete of the chat")
|
||||
Accessible.description: qsTr("Provides a button to delete the chat")
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: trashSureQuestion
|
||||
anchors.top: buttons.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.right: buttons.right
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
color: chatRectangle.color
|
||||
visible: isCurrent && trashQuestionDisplayed
|
||||
opacity: 1.0
|
||||
radius: 10
|
||||
z: 200
|
||||
Row {
|
||||
spacing: 10
|
||||
Button {
|
||||
id: checkMark
|
||||
width: 30
|
||||
height: 30
|
||||
contentItem: Text {
|
||||
color: theme.textErrorColor
|
||||
text: "\u2713"
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
background: Rectangle {
|
||||
width: 30
|
||||
height: 30
|
||||
color: "transparent"
|
||||
}
|
||||
onClicked: {
|
||||
LLM.chatListModel.removeChat(LLM.chatListModel.get(index))
|
||||
Network.sendRemoveChat()
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Confirm delete of the chat")
|
||||
Accessible.description: qsTr("Provides a button to confirm delete of the chat")
|
||||
}
|
||||
Button {
|
||||
id: cancel
|
||||
width: 30
|
||||
height: 30
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: "\u2715"
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
background: Rectangle {
|
||||
width: 30
|
||||
height: 30
|
||||
color: "transparent"
|
||||
}
|
||||
onClicked: {
|
||||
trashQuestionDisplayed = false
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Cancel the delete of the chat")
|
||||
Accessible.description: qsTr("Provides a button to cancel delete of the chat")
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 3000; running: false; repeat: false
|
||||
onTriggered: trashQuestionDisplayed = false
|
||||
}
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.List
|
||||
Accessible.name: qsTr("List of chats")
|
||||
Accessible.description: qsTr("List of chats in the drawer dialog")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: checkForUpdatesButton
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: downloadButton.top
|
||||
anchors.bottomMargin: 10
|
||||
padding: 15
|
||||
contentItem: Text {
|
||||
text: qsTr("Updates")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Use this to launch an external application that will check for updates to the installer")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (!LLM.checkForUpdates())
|
||||
checkForUpdatesError.open()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadButton
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: aboutButton.top
|
||||
anchors.bottomMargin: 10
|
||||
padding: 15
|
||||
contentItem: Text {
|
||||
text: qsTr("Downloads")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Use this to launch a dialog to download new models")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
downloadClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: aboutButton
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
padding: 15
|
||||
contentItem: Text {
|
||||
text: qsTr("About")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Use this to launch a dialog to show the about page")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
aboutClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
383
gpt4all-chat/qml/ModelDownloaderDialog.qml
Normal file
383
gpt4all-chat/qml/ModelDownloaderDialog.qml
Normal file
@@ -0,0 +1,383 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import llm
|
||||
import network
|
||||
|
||||
Dialog {
|
||||
id: modelDownloaderDialog
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
closePolicy: LLM.chatListModel.currentChat.modelList.length === 0 ? Popup.NoAutoClose : (Popup.CloseOnEscape | Popup.CloseOnPressOutside)
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -20
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
Network.sendModelDownloaderDialog();
|
||||
}
|
||||
|
||||
property string defaultModelPath: Download.defaultLocalModelsPath()
|
||||
property alias modelPath: settings.modelPath
|
||||
Settings {
|
||||
id: settings
|
||||
property string modelPath: modelDownloaderDialog.defaultModelPath
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Download.downloadLocalModelsPath = settings.modelPath
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
settings.sync()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 30
|
||||
|
||||
Label {
|
||||
id: listLabel
|
||||
text: "Available Models:"
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
color: theme.textColor
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: modelList
|
||||
model: Download.modelList
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
delegate: Item {
|
||||
id: delegateItem
|
||||
width: modelList.width
|
||||
height: modelName.height + modelName.padding
|
||||
+ description.height + description.padding
|
||||
objectName: "delegateItem"
|
||||
property bool downloading: false
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: index % 2 === 0 ? theme.backgroundLight : theme.backgroundLighter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: modelName
|
||||
objectName: "modelName"
|
||||
property string filename: modelData.filename
|
||||
text: filename.slice(5, filename.length - 4)
|
||||
padding: 20
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
font.bold: modelData.isDefault || modelData.bestGPTJ || modelData.bestLlama || modelData.bestMPT
|
||||
color: theme.assistantColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Model file")
|
||||
Accessible.description: qsTr("Model file to be downloaded")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: description
|
||||
text: " - " + modelData.description
|
||||
leftPadding: 20
|
||||
rightPadding: 20
|
||||
anchors.top: modelName.bottom
|
||||
anchors.left: modelName.left
|
||||
anchors.right: parent.right
|
||||
wrapMode: Text.WordWrap
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Description")
|
||||
Accessible.description: qsTr("The description of the file")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: isDefault
|
||||
text: qsTr("(default)")
|
||||
visible: modelData.isDefault
|
||||
anchors.top: modelName.top
|
||||
anchors.left: modelName.right
|
||||
padding: 20
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Default file")
|
||||
Accessible.description: qsTr("Whether the file is the default model")
|
||||
}
|
||||
|
||||
Text {
|
||||
text: modelData.filesize
|
||||
anchors.top: modelName.top
|
||||
anchors.left: isDefault.visible ? isDefault.right : modelName.right
|
||||
padding: 20
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("File size")
|
||||
Accessible.description: qsTr("The size of the file")
|
||||
}
|
||||
|
||||
Label {
|
||||
id: speedLabel
|
||||
anchors.top: modelName.top
|
||||
anchors.right: itemProgressBar.left
|
||||
padding: 20
|
||||
objectName: "speedLabel"
|
||||
color: theme.textColor
|
||||
text: ""
|
||||
visible: downloading
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Download speed")
|
||||
Accessible.description: qsTr("Download speed in bytes/kilobytes/megabytes per second")
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: itemProgressBar
|
||||
objectName: "itemProgressBar"
|
||||
anchors.top: modelName.top
|
||||
anchors.right: downloadButton.left
|
||||
anchors.topMargin: 20
|
||||
anchors.rightMargin: 20
|
||||
width: 100
|
||||
visible: downloading
|
||||
background: Rectangle {
|
||||
implicitWidth: 200
|
||||
implicitHeight: 30
|
||||
color: theme.backgroundDarkest
|
||||
radius: 3
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: 200
|
||||
implicitHeight: 25
|
||||
|
||||
Rectangle {
|
||||
width: itemProgressBar.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 2
|
||||
color: theme.assistantColor
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.ProgressBar
|
||||
Accessible.name: qsTr("Download progressBar")
|
||||
Accessible.description: qsTr("Shows the progress made in the download")
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: modelData.calcHash
|
||||
anchors.top: modelName.top
|
||||
anchors.right: parent.right
|
||||
|
||||
Label {
|
||||
id: calcHashLabel
|
||||
anchors.right: busyCalcHash.left
|
||||
padding: 20
|
||||
objectName: "calcHashLabel"
|
||||
color: theme.textColor
|
||||
text: qsTr("Calculating MD5...")
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Whether the file hash is being calculated")
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: busyCalcHash
|
||||
anchors.right: parent.right
|
||||
padding: 20
|
||||
running: modelData.calcHash
|
||||
Accessible.role: Accessible.Animation
|
||||
Accessible.name: qsTr("Busy indicator")
|
||||
Accessible.description: qsTr("Displayed when the file hash is being calculated")
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: installedLabel
|
||||
anchors.top: modelName.top
|
||||
anchors.right: parent.right
|
||||
padding: 20
|
||||
objectName: "installedLabel"
|
||||
color: theme.textColor
|
||||
text: qsTr("Already installed")
|
||||
visible: modelData.installed
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Whether the file is already installed on your system")
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadButton
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: downloading ? "Cancel" : "Download"
|
||||
}
|
||||
anchors.top: modelName.top
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 15
|
||||
anchors.rightMargin: 20
|
||||
visible: !modelData.installed && !modelData.calcHash
|
||||
onClicked: {
|
||||
if (!downloading) {
|
||||
downloading = true;
|
||||
Download.downloadModel(modelData.filename);
|
||||
} else {
|
||||
downloading = false;
|
||||
Download.cancelDownload(modelData.filename);
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Cancel/Download button to stop/start the download")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Download.downloadProgress.connect(updateProgress);
|
||||
Download.downloadFinished.connect(resetProgress);
|
||||
}
|
||||
|
||||
property var lastUpdate: ({})
|
||||
|
||||
function updateProgress(bytesReceived, bytesTotal, modelName) {
|
||||
let currentTime = new Date().getTime();
|
||||
|
||||
for (let i = 0; i < modelList.contentItem.children.length; i++) {
|
||||
let delegateItem = modelList.contentItem.children[i];
|
||||
if (delegateItem.objectName === "delegateItem") {
|
||||
let modelNameText = delegateItem.children.find(child => child.objectName === "modelName").filename;
|
||||
if (modelNameText === modelName) {
|
||||
let progressBar = delegateItem.children.find(child => child.objectName === "itemProgressBar");
|
||||
progressBar.value = bytesReceived / bytesTotal;
|
||||
|
||||
// Calculate the download speed
|
||||
if (lastUpdate[modelName] && lastUpdate[modelName].timestamp) {
|
||||
let timeDifference = currentTime - lastUpdate[modelName].timestamp;
|
||||
let bytesDifference = bytesReceived - lastUpdate[modelName].bytesReceived;
|
||||
let speed = (bytesDifference / timeDifference) * 1000; // bytes per second
|
||||
delegateItem.downloading = true
|
||||
|
||||
// Update the speed label
|
||||
let speedLabel = delegateItem.children.find(child => child.objectName === "speedLabel");
|
||||
if (speed < 1024) {
|
||||
speedLabel.text = speed.toFixed(2) + " B/s";
|
||||
} else if (speed < 1024 * 1024) {
|
||||
speedLabel.text = (speed / 1024).toFixed(2) + " KB/s";
|
||||
} else {
|
||||
speedLabel.text = (speed / (1024 * 1024)).toFixed(2) + " MB/s";
|
||||
}
|
||||
}
|
||||
|
||||
// Update the lastUpdate object for the current model
|
||||
lastUpdate[modelName] = {"timestamp": currentTime, "bytesReceived": bytesReceived};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetProgress(modelName) {
|
||||
for (let i = 0; i < modelList.contentItem.children.length; i++) {
|
||||
let delegateItem = modelList.contentItem.children[i];
|
||||
if (delegateItem.objectName === "delegateItem") {
|
||||
let modelNameText = delegateItem.children.find(child => child.objectName === "modelName").filename;
|
||||
if (modelNameText === modelName) {
|
||||
let progressBar = delegateItem.children.find(child => child.objectName === "itemProgressBar");
|
||||
progressBar.value = 0;
|
||||
delegateItem.downloading = false;
|
||||
|
||||
// Remove speed label text
|
||||
let speedLabel = delegateItem.children.find(child => child.objectName === "speedLabel");
|
||||
speedLabel.text = "";
|
||||
|
||||
// Remove the lastUpdate object for the canceled model
|
||||
delete lastUpdate[modelName];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.fillWidth: true
|
||||
spacing: 20
|
||||
FolderDialog {
|
||||
id: modelPathDialog
|
||||
title: "Please choose a directory"
|
||||
currentFolder: Download.downloadLocalModelsPath
|
||||
onAccepted: {
|
||||
Download.downloadLocalModelsPath = selectedFolder
|
||||
settings.modelPath = Download.downloadLocalModelsPath
|
||||
settings.sync()
|
||||
}
|
||||
}
|
||||
Label {
|
||||
id: modelPathLabel
|
||||
text: qsTr("Download path:")
|
||||
color: theme.textColor
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
}
|
||||
TextField {
|
||||
id: modelPathDisplayLabel
|
||||
text: Download.downloadLocalModelsPath
|
||||
readOnly: true
|
||||
color: theme.textColor
|
||||
Layout.fillWidth: true
|
||||
ToolTip.text: qsTr("Path where model files will be downloaded to")
|
||||
ToolTip.visible: hovered
|
||||
Accessible.role: Accessible.ToolTip
|
||||
Accessible.name: modelPathDisplayLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: qsTr("Browse")
|
||||
contentItem: Text {
|
||||
text: qsTr("Browse")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Opens a folder picker dialog to choose where to save model files")
|
||||
}
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
onClicked: modelPathDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
gpt4all-chat/qml/NetworkDialog.qml
Normal file
174
gpt4all-chat/qml/NetworkDialog.qml
Normal file
@@ -0,0 +1,174 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: networkDialog
|
||||
anchors.centerIn: parent
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
padding: 20
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
category: "network"
|
||||
property string attribution: ""
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
settings.sync()
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
spacing: 20
|
||||
Item {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
Image {
|
||||
id: img
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 60
|
||||
height: 60
|
||||
source: "qrc:/gpt4all/icons/logo.svg"
|
||||
}
|
||||
Text {
|
||||
anchors.left: img.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.verticalCenter: img.verticalCenter
|
||||
text: qsTr("Contribute data to the GPT4All Opensource Datalake.")
|
||||
color: theme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
clip: true
|
||||
height: 300
|
||||
width: 1024 - 40
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
TextArea {
|
||||
id: textOptIn
|
||||
wrapMode: Text.Wrap
|
||||
width: 1024 - 40
|
||||
padding: 20
|
||||
text: qsTr("By enabling this feature, you will be able to participate in the democratic process of training a large language model by contributing data for future model improvements.
|
||||
|
||||
When a GPT4All model responds to you and you have opted-in, your conversation will be sent to the GPT4All Open Source Datalake. Additionally, you can like/dislike its response. If you dislike a response, you can suggest an alternative response. This data will be collected and aggregated in the GPT4All Datalake.
|
||||
|
||||
NOTE: By turning on this feature, you will be sending your data to the GPT4All Open Source Datalake. You should have no expectation of chat privacy when this feature is enabled. You should; however, have an expectation of an optional attribution if you wish. Your chat data will be openly available for anyone to download and will be used by Nomic AI to improve future GPT4All models. Nomic AI will retain all attribution information attached to your data and you will be credited as a contributor to any GPT4All model release that uses your data!")
|
||||
color: theme.textColor
|
||||
focus: false
|
||||
readOnly: true
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Terms for opt-in")
|
||||
Accessible.description: qsTr("Describes what will happen when you opt-in")
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLight
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: attribution
|
||||
color: theme.textColor
|
||||
padding: 20
|
||||
width: parent.width
|
||||
text: settings.attribution
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
placeholderText: qsTr("Please provide a name for attribution (optional)")
|
||||
placeholderTextColor: theme.backgroundLightest
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: qsTr("Attribution (optional)")
|
||||
Accessible.description: qsTr("Textfield for providing attribution")
|
||||
onEditingFinished: {
|
||||
settings.attribution = attribution.text;
|
||||
settings.sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
footer: DialogButtonBox {
|
||||
id: dialogBox
|
||||
padding: 20
|
||||
alignment: Qt.AlignRight
|
||||
spacing: 10
|
||||
Button {
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: qsTr("Enable")
|
||||
}
|
||||
background: Rectangle {
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Enable opt-in button")
|
||||
|
||||
padding: 15
|
||||
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
|
||||
}
|
||||
Button {
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: qsTr("Cancel")
|
||||
}
|
||||
background: Rectangle {
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Cancel opt-in button")
|
||||
|
||||
padding: 15
|
||||
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
|
||||
}
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (Network.isActive)
|
||||
return
|
||||
Network.isActive = true;
|
||||
Network.sendNetworkToggled(true);
|
||||
}
|
||||
|
||||
onRejected: {
|
||||
if (!Network.isActive)
|
||||
return
|
||||
Network.isActive = false;
|
||||
Network.sendNetworkToggled(false);
|
||||
}
|
||||
}
|
76
gpt4all-chat/qml/NewVersionDialog.qml
Normal file
76
gpt4all-chat/qml/NewVersionDialog.qml
Normal file
@@ -0,0 +1,76 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: newVerionDialog
|
||||
anchors.centerIn: parent
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
width: contentItem.width
|
||||
height: contentItem.height
|
||||
padding: 20
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contentItem
|
||||
width: childrenRect.width + 40
|
||||
height: childrenRect.height + 40
|
||||
|
||||
Label {
|
||||
id: label
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
topPadding: 20
|
||||
bottomPadding: 20
|
||||
text: qsTr("New version is available:")
|
||||
color: theme.textColor
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
anchors.left: label.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.verticalCenter: label.verticalCenter
|
||||
padding: 20
|
||||
contentItem: Text {
|
||||
text: qsTr("Update")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Use this to launch an external application that will check for updates to the installer")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (!LLM.checkForUpdates())
|
||||
checkForUpdatesError.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
gpt4all-chat/qml/PopupDialog.qml
Normal file
71
gpt4all-chat/qml/PopupDialog.qml
Normal file
@@ -0,0 +1,71 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
|
||||
Dialog {
|
||||
id: popupDialog
|
||||
anchors.centerIn: parent
|
||||
opacity: 0.9
|
||||
padding: 20
|
||||
property alias text: textField.text
|
||||
property bool shouldTimeOut: true
|
||||
property bool shouldShowBusy: false
|
||||
modal: shouldShowBusy
|
||||
closePolicy: shouldShowBusy ? Popup.NoAutoClose : (Popup.CloseOnEscape | Popup.CloseOnPressOutside)
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
spacing: 20
|
||||
|
||||
Text {
|
||||
id: textField
|
||||
anchors.verticalCenter: busyIndicator.verticalCenter
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.HelpBalloon
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Reveals a shortlived help balloon")
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: busyIndicator
|
||||
visible: shouldShowBusy
|
||||
running: shouldShowBusy
|
||||
|
||||
Accessible.role: Accessible.Animation
|
||||
Accessible.name: qsTr("Busy indicator")
|
||||
Accessible.description: qsTr("Displayed when the popup is showing busy")
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
exit: Transition {
|
||||
NumberAnimation { duration: 500; property: "opacity"; from: 1.0; to: 0.0 }
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
if (shouldTimeOut)
|
||||
timer.start()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 500; running: false; repeat: false
|
||||
onTriggered: popupDialog.close()
|
||||
}
|
||||
}
|
828
gpt4all-chat/qml/SettingsDialog.qml
Normal file
828
gpt4all-chat/qml/SettingsDialog.qml
Normal file
@@ -0,0 +1,828 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: settingsDialog
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -20
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
Network.sendSettingsDialog();
|
||||
}
|
||||
|
||||
property var currentChat: LLM.chatListModel.currentChat
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
property real defaultTemperature: 0.28
|
||||
property real defaultTopP: 0.95
|
||||
property int defaultTopK: 40
|
||||
property int defaultMaxLength: 4096
|
||||
property int defaultPromptBatchSize: 9
|
||||
property real defaultRepeatPenalty: 1.10
|
||||
property int defaultRepeatPenaltyTokens: 64
|
||||
property int defaultThreadCount: 0
|
||||
property bool defaultSaveChats: false
|
||||
property string defaultPromptTemplate: "### Human:
|
||||
%1
|
||||
### Assistant:\n"
|
||||
property string defaultModelPath: Download.defaultLocalModelsPath()
|
||||
property string defaultUserDefaultModel: "Application default"
|
||||
|
||||
property alias temperature: settings.temperature
|
||||
property alias topP: settings.topP
|
||||
property alias topK: settings.topK
|
||||
property alias maxLength: settings.maxLength
|
||||
property alias promptBatchSize: settings.promptBatchSize
|
||||
property alias promptTemplate: settings.promptTemplate
|
||||
property alias repeatPenalty: settings.repeatPenalty
|
||||
property alias repeatPenaltyTokens: settings.repeatPenaltyTokens
|
||||
property alias threadCount: settings.threadCount
|
||||
property alias saveChats: settings.saveChats
|
||||
property alias modelPath: settings.modelPath
|
||||
property alias userDefaultModel: settings.userDefaultModel
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
property real temperature: settingsDialog.defaultTemperature
|
||||
property real topP: settingsDialog.defaultTopP
|
||||
property int topK: settingsDialog.defaultTopK
|
||||
property int maxLength: settingsDialog.defaultMaxLength
|
||||
property int promptBatchSize: settingsDialog.defaultPromptBatchSize
|
||||
property int threadCount: settingsDialog.defaultThreadCount
|
||||
property bool saveChats: settingsDialog.defaultSaveChats
|
||||
property real repeatPenalty: settingsDialog.defaultRepeatPenalty
|
||||
property int repeatPenaltyTokens: settingsDialog.defaultRepeatPenaltyTokens
|
||||
property string promptTemplate: settingsDialog.defaultPromptTemplate
|
||||
property string modelPath: settingsDialog.defaultModelPath
|
||||
property string userDefaultModel: settingsDialog.defaultUserDefaultModel
|
||||
}
|
||||
|
||||
function restoreGenerationDefaults() {
|
||||
settings.temperature = defaultTemperature
|
||||
settings.topP = defaultTopP
|
||||
settings.topK = defaultTopK
|
||||
settings.maxLength = defaultMaxLength
|
||||
settings.promptBatchSize = defaultPromptBatchSize
|
||||
settings.promptTemplate = defaultPromptTemplate
|
||||
settings.repeatPenalty = defaultRepeatPenalty
|
||||
settings.repeatPenaltyTokens = defaultRepeatPenaltyTokens
|
||||
settings.sync()
|
||||
}
|
||||
|
||||
function restoreApplicationDefaults() {
|
||||
settings.modelPath = settingsDialog.defaultModelPath
|
||||
settings.threadCount = defaultThreadCount
|
||||
settings.saveChats = defaultSaveChats
|
||||
settings.userDefaultModel = defaultUserDefaultModel
|
||||
Download.downloadLocalModelsPath = settings.modelPath
|
||||
LLM.threadCount = settings.threadCount
|
||||
LLM.chatListModel.shouldSaveChats = settings.saveChats
|
||||
settings.sync()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
LLM.threadCount = settings.threadCount
|
||||
LLM.chatListModel.shouldSaveChats = settings.saveChats
|
||||
Download.downloadLocalModelsPath = settings.modelPath
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: settingsDialog
|
||||
function onClosed() {
|
||||
settings.sync()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Accessible.role: Accessible.Dialog
|
||||
Accessible.name: qsTr("Settings dialog")
|
||||
Accessible.description: qsTr("Dialog containing various application settings")
|
||||
}
|
||||
TabBar {
|
||||
id: settingsTabBar
|
||||
width: parent.width / 1.5
|
||||
|
||||
TabButton {
|
||||
id: genSettingsButton
|
||||
contentItem: IconLabel {
|
||||
color: theme.textColor
|
||||
font.bold: genSettingsButton.checked
|
||||
font.pixelSize: genSettingsButton.checked ? theme.fontSizeLarger : theme.fontSizeLarge
|
||||
text: qsTr("Generation")
|
||||
}
|
||||
background: Rectangle {
|
||||
color: genSettingsButton.checked ? theme.backgroundDarkest : theme.backgroundLight
|
||||
border.color: theme.tabBorder
|
||||
border.width: 1 ? genSettingsButton.checked : 0
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Generation settings")
|
||||
Accessible.description: qsTr("Settings related to how the model generates text")
|
||||
}
|
||||
|
||||
TabButton {
|
||||
id: appSettingsButton
|
||||
contentItem: IconLabel {
|
||||
color: theme.textColor
|
||||
font.bold: appSettingsButton.checked
|
||||
font.pixelSize: appSettingsButton.checked ? theme.fontSizeLarger : theme.fontSizeLarge
|
||||
text: qsTr("Application")
|
||||
}
|
||||
background: Rectangle {
|
||||
color: appSettingsButton.checked ? theme.backgroundDarkest : theme.backgroundLight
|
||||
border.color: theme.tabBorder
|
||||
border.width: 1 ? appSettingsButton.checked : 0
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Application settings")
|
||||
Accessible.description: qsTr("Settings related to general behavior of the application")
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
anchors.top: settingsTabBar.bottom
|
||||
width: parent.width
|
||||
height: availableHeight
|
||||
currentIndex: settingsTabBar.currentIndex
|
||||
|
||||
Item {
|
||||
id: generationSettingsTab
|
||||
ScrollView {
|
||||
background: Rectangle {
|
||||
color: 'transparent'
|
||||
border.color: theme.tabBorder
|
||||
border.width: 1
|
||||
radius: 2
|
||||
}
|
||||
padding: 10
|
||||
width: parent.width
|
||||
height: parent.height - 30
|
||||
contentWidth: availableWidth - 20
|
||||
contentHeight: generationSettingsTabInner.implicitHeight + 40
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
|
||||
GridLayout {
|
||||
id: generationSettingsTabInner
|
||||
anchors.margins: 10
|
||||
columns: 2
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
id: tempLabel
|
||||
text: qsTr("Temperature:")
|
||||
color: theme.textColor
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
}
|
||||
TextField {
|
||||
text: settings.temperature.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
ToolTip.text: qsTr("Temperature increases the chances of choosing less likely tokens - 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)) {
|
||||
settings.temperature = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.temperature.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.topP.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen, 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)) {
|
||||
settings.topP = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.topP.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.topK.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
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)) {
|
||||
settings.topK = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.topK.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.maxLength.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
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)) {
|
||||
settings.maxLength = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.maxLength.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.promptBatchSize.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
ToolTip.text: qsTr("Amount of prompt tokens to process at once, 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)) {
|
||||
settings.promptBatchSize = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.promptBatchSize.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.repeatPenalty.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
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)) {
|
||||
settings.repeatPenalty = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.repeatPenalty.toString()
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
TextField {
|
||||
text: settings.repeatPenaltyTokens.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
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)) {
|
||||
settings.repeatPenaltyTokens = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settings.repeatPenaltyTokens.toString()
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: repeatPenaltyTokensLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
|
||||
Label {
|
||||
id: promptTemplateLabel
|
||||
text: qsTr("Prompt Template:")
|
||||
color: theme.textColor
|
||||
Layout.row: 7
|
||||
Layout.column: 0
|
||||
}
|
||||
Rectangle {
|
||||
Layout.row: 7
|
||||
Layout.column: 1
|
||||
Layout.fillWidth: true
|
||||
height: 200
|
||||
color: "transparent"
|
||||
clip: true
|
||||
Label {
|
||||
id: promptTemplateLabelHelp
|
||||
visible: settings.promptTemplate.indexOf(
|
||||
"%1") === -1
|
||||
font.bold: true
|
||||
color: theme.textErrorColor
|
||||
text: qsTr("Prompt template must contain %1 to be replaced with the user's input.")
|
||||
anchors.fill: templateScrollView
|
||||
z: 200
|
||||
padding: 10
|
||||
wrapMode: TextArea.Wrap
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: text
|
||||
}
|
||||
ScrollView {
|
||||
id: templateScrollView
|
||||
anchors.fill: parent
|
||||
TextArea {
|
||||
text: settings.promptTemplate
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
wrapMode: TextArea.Wrap
|
||||
onTextChanged: {
|
||||
settings.promptTemplate = text
|
||||
settings.sync()
|
||||
}
|
||||
bottomPadding: 10
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: promptTemplateLabel.text
|
||||
Accessible.description: promptTemplateLabelHelp.text
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.row: 8
|
||||
Layout.column: 1
|
||||
Layout.fillWidth: true
|
||||
padding: 10
|
||||
contentItem: Text {
|
||||
text: qsTr("Restore Defaults")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Restores the settings dialog to a default state")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
onClicked: {
|
||||
settingsDialog.restoreGenerationDefaults()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: applicationSettingsTab
|
||||
ScrollView {
|
||||
background: Rectangle {
|
||||
color: 'transparent'
|
||||
border.color: theme.tabBorder
|
||||
border.width: 1
|
||||
radius: 2
|
||||
}
|
||||
padding: 10
|
||||
width: parent.width
|
||||
height: parent.height - 30
|
||||
contentWidth: availableWidth - 20
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
|
||||
GridLayout {
|
||||
anchors.margins: 10
|
||||
columns: 3
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
id: defaultModelLabel
|
||||
text: qsTr("Default model:")
|
||||
color: theme.textColor
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
}
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
Layout.row: 1
|
||||
Layout.column: 1
|
||||
Layout.minimumWidth: 350
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
spacing: 0
|
||||
padding: 10
|
||||
model: modelList
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: qsTr("ComboBox for displaying/picking the default model")
|
||||
Accessible.description: qsTr("Use this for picking the default model to use; the first item is the current default model")
|
||||
function updateModel(newModelList) {
|
||||
var newArray = Array.from(newModelList);
|
||||
newArray.unshift('Application default');
|
||||
comboBox.model = newArray;
|
||||
settings.sync();
|
||||
comboBox.currentIndex = comboBox.indexOfValue(settingsDialog.userDefaultModel);
|
||||
|
||||
}
|
||||
Component.onCompleted: {
|
||||
comboBox.updateModel(currentChat.modelList)
|
||||
}
|
||||
Connections {
|
||||
target: settings
|
||||
function onUserDefaultModelChanged() {
|
||||
comboBox.updateModel(currentChat.modelList)
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: currentChat
|
||||
function onModelListChanged() {
|
||||
comboBox.updateModel(currentChat.modelList)
|
||||
}
|
||||
}
|
||||
contentItem: Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
text: comboBox.displayText
|
||||
font: comboBox.font
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
delegate: ItemDelegate {
|
||||
width: comboBox.width
|
||||
contentItem: Text {
|
||||
text: modelData
|
||||
color: theme.textColor
|
||||
font: comboBox.font
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
background: Rectangle {
|
||||
color: highlighted ? theme.backgroundLight : theme.backgroundDark
|
||||
}
|
||||
highlighted: comboBox.highlightedIndex === index
|
||||
}
|
||||
popup: Popup {
|
||||
y: comboBox.height - 1
|
||||
width: comboBox.width
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
padding: 0
|
||||
|
||||
contentItem: ListView {
|
||||
clip: true
|
||||
implicitHeight: contentHeight
|
||||
model: comboBox.popup.visible ? comboBox.delegateModel : null
|
||||
currentIndex: comboBox.highlightedIndex
|
||||
ScrollIndicator.vertical: ScrollIndicator { }
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: theme.backgroundDark
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: theme.backgroundDark
|
||||
border.width: 1
|
||||
border.color: theme.backgroundLightest
|
||||
radius: 10
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
settingsDialog.userDefaultModel = comboBox.currentText
|
||||
settings.sync()
|
||||
}
|
||||
}
|
||||
FolderDialog {
|
||||
id: modelPathDialog
|
||||
title: "Please choose a directory"
|
||||
currentFolder: Download.downloadLocalModelsPath
|
||||
onAccepted: {
|
||||
Download.downloadLocalModelsPath = selectedFolder
|
||||
settings.modelPath = Download.downloadLocalModelsPath
|
||||
settings.sync()
|
||||
}
|
||||
}
|
||||
Label {
|
||||
id: modelPathLabel
|
||||
text: qsTr("Download path:")
|
||||
color: theme.textColor
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
}
|
||||
TextField {
|
||||
id: modelPathDisplayLabel
|
||||
text: Download.downloadLocalModelsPath
|
||||
readOnly: true
|
||||
color: theme.textColor
|
||||
implicitWidth: 300
|
||||
padding: 10
|
||||
Layout.row: 2
|
||||
Layout.column: 1
|
||||
Layout.fillWidth: true
|
||||
ToolTip.text: qsTr("Path where model files will be downloaded to")
|
||||
ToolTip.visible: hovered
|
||||
Accessible.role: Accessible.ToolTip
|
||||
Accessible.name: modelPathDisplayLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.row: 2
|
||||
Layout.column: 2
|
||||
text: qsTr("Browse")
|
||||
contentItem: Text {
|
||||
text: qsTr("Browse")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Opens a folder picker dialog to choose where to save model files")
|
||||
}
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
onClicked: modelPathDialog.open()
|
||||
}
|
||||
Label {
|
||||
id: nThreadsLabel
|
||||
text: qsTr("CPU Threads:")
|
||||
color: theme.textColor
|
||||
Layout.row: 3
|
||||
Layout.column: 0
|
||||
}
|
||||
TextField {
|
||||
text: settingsDialog.threadCount.toString()
|
||||
color: theme.textColor
|
||||
background: Rectangle {
|
||||
implicitWidth: 150
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
padding: 10
|
||||
ToolTip.text: qsTr("Amount of processing threads to use, a setting of 0 will use the lesser of 4 or your number of CPU threads")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 3
|
||||
Layout.column: 1
|
||||
validator: IntValidator {
|
||||
bottom: 1
|
||||
}
|
||||
onEditingFinished: {
|
||||
var val = parseInt(text)
|
||||
if (!isNaN(val)) {
|
||||
settingsDialog.threadCount = val
|
||||
LLM.threadCount = val
|
||||
settings.sync()
|
||||
focus = false
|
||||
} else {
|
||||
text = settingsDialog.threadCount.toString()
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: nThreadsLabel.text
|
||||
Accessible.description: ToolTip.text
|
||||
}
|
||||
Label {
|
||||
id: saveChatsLabel
|
||||
text: qsTr("Save chats to disk:")
|
||||
color: theme.textColor
|
||||
Layout.row: 4
|
||||
Layout.column: 0
|
||||
}
|
||||
CheckBox {
|
||||
id: saveChatsBox
|
||||
Layout.row: 4
|
||||
Layout.column: 1
|
||||
checked: settingsDialog.saveChats
|
||||
onClicked: {
|
||||
Network.sendSaveChatsToggled(saveChatsBox.checked);
|
||||
settingsDialog.saveChats = saveChatsBox.checked
|
||||
LLM.chatListModel.shouldSaveChats = saveChatsBox.checked
|
||||
settings.sync()
|
||||
}
|
||||
|
||||
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
|
||||
ToolTip.visible: hovered
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
x: saveChatsBox.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
border.color: theme.dialogBorder
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
x: 6
|
||||
y: 6
|
||||
color: theme.textColor
|
||||
visible: saveChatsBox.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: saveChatsBox.text
|
||||
font: saveChatsBox.font
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: saveChatsBox.indicator.width + saveChatsBox.spacing
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.row: 5
|
||||
Layout.column: 1
|
||||
Layout.fillWidth: true
|
||||
padding: 10
|
||||
contentItem: Text {
|
||||
text: qsTr("Restore Defaults")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Restores the settings dialog to a default state")
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: .5
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
onClicked: {
|
||||
settingsDialog.restoreApplicationDefaults()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
357
gpt4all-chat/qml/StartupDialog.qml
Normal file
357
gpt4all-chat/qml/StartupDialog.qml
Normal file
@@ -0,0 +1,357 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: startupDialog
|
||||
anchors.centerIn: parent
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
padding: 20
|
||||
width: 1024
|
||||
height: column.height + 40
|
||||
closePolicy: !optInStatisticsRadio.choiceMade || !optInNetworkRadio.choiceMade ? Popup.NoAutoClose : (Popup.CloseOnEscape | Popup.CloseOnPressOutside)
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
spacing: 20
|
||||
Item {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
Image {
|
||||
id: img
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 60
|
||||
height: 60
|
||||
source: "qrc:/gpt4all/icons/logo.svg"
|
||||
}
|
||||
Text {
|
||||
anchors.left: img.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.verticalCenter: img.verticalCenter
|
||||
text: qsTr("Welcome!")
|
||||
color: theme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
clip: true
|
||||
height: 200
|
||||
width: 1024 - 40
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
TextArea {
|
||||
id: welcome
|
||||
wrapMode: Text.Wrap
|
||||
width: 1024 - 40
|
||||
padding: 20
|
||||
textFormat: TextEdit.MarkdownText
|
||||
text: qsTr("### Release notes\n")
|
||||
+ Download.releaseInfo.notes
|
||||
+ qsTr("### Contributors\n")
|
||||
+ Download.releaseInfo.contributors
|
||||
color: theme.textColor
|
||||
focus: false
|
||||
readOnly: true
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Release notes")
|
||||
Accessible.description: qsTr("Release notes for this version")
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLight
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
clip: true
|
||||
height: 150
|
||||
width: 1024 - 40
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
TextArea {
|
||||
id: optInTerms
|
||||
wrapMode: Text.Wrap
|
||||
width: 1024 - 40
|
||||
padding: 20
|
||||
textFormat: TextEdit.MarkdownText
|
||||
text: qsTr(
|
||||
"### Opt-ins for anonymous usage analytics and datalake
|
||||
By enabling these features, you will be able to participate in the democratic process of training a
|
||||
large language model by contributing data for future model improvements.
|
||||
|
||||
When a GPT4All model responds to you and you have opted-in, your conversation will be sent to the GPT4All
|
||||
Open Source Datalake. Additionally, you can like/dislike its response. If you dislike a response, you
|
||||
can suggest an alternative response. This data will be collected and aggregated in the GPT4All Datalake.
|
||||
|
||||
NOTE: By turning on this feature, you will be sending your data to the GPT4All Open Source Datalake.
|
||||
You should have no expectation of chat privacy when this feature is enabled. You should; however, have
|
||||
an expectation of an optional attribution if you wish. Your chat data will be openly available for anyone
|
||||
to download and will be used by Nomic AI to improve future GPT4All models. Nomic AI will retain all
|
||||
attribution information attached to your data and you will be credited as a contributor to any GPT4All
|
||||
model release that uses your data!")
|
||||
|
||||
color: theme.textColor
|
||||
focus: false
|
||||
readOnly: true
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Terms for opt-in")
|
||||
Accessible.description: qsTr("Describes what will happen when you opt-in")
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLight
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
anchors.right: parent.right
|
||||
Label {
|
||||
id: optInStatistics
|
||||
text: "Opt-in to anonymous usage analytics used to improve GPT4All"
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Opt-in for anonymous usage statistics")
|
||||
Accessible.description: qsTr("Label for opt-in")
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
buttons: optInStatisticsRadio.children
|
||||
onClicked: {
|
||||
Network.usageStatsActive = optInStatisticsRadio.checked
|
||||
if (optInNetworkRadio.choiceMade && optInStatisticsRadio.choiceMade)
|
||||
startupDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: optInStatisticsRadio
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.row: 0
|
||||
Layout.column: 1
|
||||
property bool defaultChecked: Network.usageStatsActive
|
||||
property alias checked: optInStatisticsRadioYes.checked
|
||||
property bool choiceMade: optInStatisticsRadioYes.checked || optInStatisticsRadioNo.checked
|
||||
|
||||
RadioButton {
|
||||
id: optInStatisticsRadioYes
|
||||
checked: optInStatisticsRadio.defaultChecked
|
||||
text: qsTr("Yes")
|
||||
Accessible.role: Accessible.RadioButton
|
||||
Accessible.name: qsTr("Opt-in for anonymous usage statistics")
|
||||
Accessible.description: qsTr("Radio button to allow opt-in for anonymous usage statistics")
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
x: optInStatisticsRadioYes.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
radius: 13
|
||||
border.color: theme.dialogBorder
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
x: 6
|
||||
y: 6
|
||||
radius: 7
|
||||
color: theme.textColor
|
||||
visible: optInStatisticsRadioYes.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: optInStatisticsRadioYes.text
|
||||
font: optInStatisticsRadioYes.font
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: optInStatisticsRadioYes.indicator.width + optInStatisticsRadioYes.spacing
|
||||
}
|
||||
}
|
||||
RadioButton {
|
||||
id: optInStatisticsRadioNo
|
||||
text: qsTr("No")
|
||||
Accessible.role: Accessible.RadioButton
|
||||
Accessible.name: qsTr("Opt-out for anonymous usage statistics")
|
||||
Accessible.description: qsTr("Radio button to allow opt-out for anonymous usage statistics")
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
x: optInStatisticsRadioNo.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
radius: 13
|
||||
border.color: theme.dialogBorder
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
x: 6
|
||||
y: 6
|
||||
radius: 7
|
||||
color: theme.textColor
|
||||
visible: optInStatisticsRadioNo.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: optInStatisticsRadioNo.text
|
||||
font: optInStatisticsRadioNo.font
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: optInStatisticsRadioNo.indicator.width + optInStatisticsRadioNo.spacing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: optInNetwork
|
||||
text: "Opt-in to anonymous sharing of chats to the GPT4All Datalake"
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
color: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Opt-in for network")
|
||||
Accessible.description: qsTr("Checkbox to allow opt-in for network")
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
buttons: optInNetworkRadio.children
|
||||
onClicked: {
|
||||
Network.isActive = optInNetworkRadio.checked
|
||||
if (optInNetworkRadio.choiceMade && optInStatisticsRadio.choiceMade)
|
||||
startupDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: optInNetworkRadio
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.row: 1
|
||||
Layout.column: 1
|
||||
property bool defaultChecked: Network.isActive
|
||||
property alias checked: optInNetworkRadioYes.checked
|
||||
property bool choiceMade: optInNetworkRadioYes.checked || optInNetworkRadioNo.checked
|
||||
|
||||
RadioButton {
|
||||
id: optInNetworkRadioYes
|
||||
checked: optInNetworkRadio.defaultChecked
|
||||
text: qsTr("Yes")
|
||||
Accessible.role: Accessible.RadioButton
|
||||
Accessible.name: qsTr("Opt-in for network")
|
||||
Accessible.description: qsTr("Radio button to allow opt-in anonymous sharing of chats to the GPT4All Datalake")
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
x: optInNetworkRadioYes.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
radius: 13
|
||||
border.color: theme.dialogBorder
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
x: 6
|
||||
y: 6
|
||||
radius: 7
|
||||
color: theme.textColor
|
||||
visible: optInNetworkRadioYes.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: optInNetworkRadioYes.text
|
||||
font: optInNetworkRadioYes.font
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: optInNetworkRadioYes.indicator.width + optInNetworkRadioYes.spacing
|
||||
}
|
||||
}
|
||||
RadioButton {
|
||||
id: optInNetworkRadioNo
|
||||
text: qsTr("No")
|
||||
Accessible.role: Accessible.RadioButton
|
||||
Accessible.name: qsTr("Opt-out for network")
|
||||
Accessible.description: qsTr("Radio button to allow opt-out anonymous sharing of chats to the GPT4All Datalake")
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 26
|
||||
implicitHeight: 26
|
||||
x: optInNetworkRadioNo.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
radius: 13
|
||||
border.color: theme.dialogBorder
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: 14
|
||||
height: 14
|
||||
x: 6
|
||||
y: 6
|
||||
radius: 7
|
||||
color: theme.textColor
|
||||
visible: optInNetworkRadioNo.checked
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
text: optInNetworkRadioNo.text
|
||||
font: optInNetworkRadioNo.font
|
||||
opacity: enabled ? 1.0 : 0.3
|
||||
color: theme.textColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: optInNetworkRadioNo.indicator.width + optInNetworkRadioNo.spacing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
}
|
20
gpt4all-chat/qml/Theme.qml
Normal file
20
gpt4all-chat/qml/Theme.qml
Normal file
@@ -0,0 +1,20 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls.Basic
|
||||
|
||||
QtObject {
|
||||
property color textColor: "#d1d5db"
|
||||
property color textErrorColor: "red"
|
||||
property color backgroundDarkest: "#202123"
|
||||
property color backgroundDark: "#242528"
|
||||
property color backgroundLight: "#343541"
|
||||
property color backgroundLighter: "#444654"
|
||||
property color backgroundLightest: "#7d7d8e"
|
||||
property color dialogBorder: "#d1d5db"
|
||||
property color userColor: "#ec86bf"
|
||||
property color assistantColor: "#10a37f"
|
||||
property color linkColor: "white"
|
||||
property color tabBorder: "#aaa"
|
||||
property real fontSizeLarge: Qt.application.font.pixelSize
|
||||
property real fontSizeLarger: Qt.application.font.pixelSize + 2
|
||||
}
|
112
gpt4all-chat/qml/ThumbsDownDialog.qml
Normal file
112
gpt4all-chat/qml/ThumbsDownDialog.qml
Normal file
@@ -0,0 +1,112 @@
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Controls.Basic
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import network
|
||||
import llm
|
||||
|
||||
Dialog {
|
||||
id: thumbsDownDialog
|
||||
modal: true
|
||||
opacity: 0.9
|
||||
padding: 20
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
||||
property alias response: thumbsDownNewResponse.text
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 20
|
||||
Item {
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
Image {
|
||||
id: img
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 60
|
||||
height: 60
|
||||
source: "qrc:/gpt4all/icons/thumbs_down.svg"
|
||||
}
|
||||
Text {
|
||||
anchors.left: img.right
|
||||
anchors.leftMargin: 30
|
||||
anchors.verticalCenter: img.verticalCenter
|
||||
text: qsTr("Please edit the text below to provide a better response. (optional)")
|
||||
color: theme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
clip: true
|
||||
height: 300
|
||||
width: parent.width
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
TextArea {
|
||||
id: thumbsDownNewResponse
|
||||
color: theme.textColor
|
||||
padding: 20
|
||||
wrapMode: Text.Wrap
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
placeholderText: qsTr("Please provide a better response...")
|
||||
placeholderTextColor: theme.backgroundLightest
|
||||
background: Rectangle {
|
||||
color: theme.backgroundLighter
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.backgroundDarkest
|
||||
border.width: 1
|
||||
border.color: theme.dialogBorder
|
||||
radius: 10
|
||||
}
|
||||
|
||||
footer: DialogButtonBox {
|
||||
padding: 20
|
||||
alignment: Qt.AlignRight
|
||||
spacing: 10
|
||||
Button {
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: qsTr("Submit")
|
||||
}
|
||||
background: Rectangle {
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
padding: 15
|
||||
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
|
||||
}
|
||||
Button {
|
||||
contentItem: Text {
|
||||
color: theme.textColor
|
||||
text: qsTr("Cancel")
|
||||
}
|
||||
background: Rectangle {
|
||||
border.color: theme.backgroundLightest
|
||||
border.width: 1
|
||||
radius: 10
|
||||
color: theme.backgroundLight
|
||||
}
|
||||
padding: 15
|
||||
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
|
||||
}
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user