gpt4all/gpt4all-chat/qml/ModelDownloaderDialog.qml

442 lines
22 KiB
QML
Raw Normal View History

import QtCore
import QtQuick
import QtQuick.Controls
2023-04-23 23:56:33 -04:00
import QtQuick.Controls.Basic
import QtQuick.Dialogs
import QtQuick.Layouts
2023-06-22 15:44:49 -04:00
import chatlistmodel
2023-04-18 21:10:06 -04:00
import download
import llm
2023-06-22 15:44:49 -04:00
import modellist
import network
import mysettings
2023-04-18 21:10:06 -04:00
2023-07-06 10:53:43 -04:00
MyDialog {
2023-04-18 21:10:06 -04:00
id: modelDownloaderDialog
modal: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
2023-07-06 10:53:43 -04:00
padding: 10
property bool showEmbeddingModels: false
2023-04-18 21:10:06 -04:00
onOpened: {
Network.sendModelDownloaderDialog();
if (showEmbeddingModels) {
ModelList.downloadableModels.expanded = true
var targetModelIndex = ModelList.defaultEmbeddingModelIndex
modelListView.positionViewAtIndex(targetModelIndex, ListView.Contain)
}
}
2023-06-22 15:44:49 -04:00
PopupDialog {
id: downloadingErrorPopup
anchors.centerIn: parent
shouldTimeOut: false
}
2023-04-18 21:10:06 -04:00
ColumnLayout {
anchors.fill: parent
2023-07-06 10:53:43 -04:00
anchors.margins: 10
spacing: 30
2023-04-18 21:10:06 -04:00
Label {
id: listLabel
text: qsTr("Available Models")
2023-04-18 21:10:06 -04:00
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
color: theme.titleTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
2023-04-18 21:10:06 -04:00
}
Label {
visible: !ModelList.downloadableModels.count && !ModelList.asyncModelRequestOngoing
2023-06-20 17:40:02 -04:00
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
text: qsTr("Network error: could not retrieve http://gpt4all.io/models/models2.json")
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
color: theme.mutedTextColor
}
MyBusyIndicator {
visible: !ModelList.downloadableModels.count && ModelList.asyncModelRequestOngoing
running: ModelList.asyncModelRequestOngoing
Accessible.role: Accessible.Animation
2023-07-12 11:51:07 -04:00
Layout.alignment: Qt.AlignCenter
Accessible.name: qsTr("Busy indicator")
Accessible.description: qsTr("Displayed when the models request is ongoing")
}
ScrollView {
id: scrollView
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
2023-04-18 21:10:06 -04:00
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ListView {
2023-06-22 15:44:49 -04:00
id: modelListView
model: ModelList.downloadableModels
boundsBehavior: Flickable.StopAtBounds
2023-06-22 15:44:49 -04:00
delegate: Rectangle {
id: delegateItem
2023-06-22 15:44:49 -04:00
width: modelListView.width
height: childrenRect.height
color: index % 2 === 0 ? theme.darkContrast : theme.lightContrast
2023-06-22 15:44:49 -04:00
GridLayout {
columns: 2
width: parent.width
Text {
textFormat: Text.StyledText
text: "<h2>" + name + "</h2>"
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarger
2023-06-22 15:44:49 -04:00
Layout.row: 0
Layout.column: 0
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.columnSpan: 2
color: theme.titleTextColor
2023-06-22 15:44:49 -04:00
Accessible.role: Accessible.Paragraph
Accessible.name: qsTr("Model file")
Accessible.description: qsTr("Model file to be downloaded")
}
2023-04-18 21:10:06 -04:00
2023-06-22 15:44:49 -04:00
Rectangle {
id: actionBox
width: childrenRect.width + 20
color: theme.containerBackground
border.color: theme.yellowAccent
2023-06-22 15:44:49 -04:00
border.width: 1
radius: 10
Layout.row: 1
Layout.column: 1
Layout.rightMargin: 20
Layout.bottomMargin: 20
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height + 20
Layout.alignment: Qt.AlignRight | Qt.AlignTop
Layout.rowSpan: 2
ColumnLayout {
spacing: 0
MySettingsButton {
2023-06-22 15:44:49 -04:00
id: downloadButton
text: isDownloading ? qsTr("Cancel") : isIncomplete ? qsTr("Resume") : qsTr("Download")
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: openaiKey.width
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
visible: !isChatGPT && !installed && !calcHash && downloadError === ""
Accessible.description: qsTr("Stop/restart/start the download")
2023-06-22 15:44:49 -04:00
onClicked: {
if (!isDownloading) {
Download.downloadModel(filename);
} else {
Download.cancelDownload(filename);
}
}
}
2023-04-18 21:10:06 -04:00
MySettingsDestructiveButton {
2023-06-22 15:44:49 -04:00
id: removeButton
text: qsTr("Remove")
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: openaiKey.width
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
visible: installed || downloadError !== ""
Accessible.description: qsTr("Remove model from filesystem")
2023-06-22 15:44:49 -04:00
onClicked: {
Download.removeModel(filename);
}
}
MySettingsButton {
2023-06-22 15:44:49 -04:00
id: installButton
visible: !installed && isChatGPT
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: openaiKey.width
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
text: qsTr("Install")
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
onClicked: {
if (openaiKey.text === "")
openaiKey.showError();
else
Download.installModel(filename, openaiKey.text);
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Install")
Accessible.description: qsTr("Install chatGPT model")
2023-06-22 15:44:49 -04:00
}
2023-06-22 15:44:49 -04:00
ColumnLayout {
spacing: 0
Label {
Layout.topMargin: 20
Layout.leftMargin: 20
textFormat: Text.StyledText
text: "<strong><font size=\"1\">"
+ (qsTr("Status: ")
+ (installed ? qsTr("Installed")
: (downloadError !== "" ? qsTr("<a href=\"#error\">Error</a>")
: (isDownloading ? qsTr("Downloading") : qsTr("Available")))))
+ "</strong></font>"
color: theme.textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-07-05 20:12:37 -04:00
linkColor: theme.textErrorColor
2023-06-22 15:44:49 -04:00
Accessible.role: Accessible.Paragraph
Accessible.name: text
Accessible.description: qsTr("Whether the file is already installed on your system")
onLinkActivated: {
downloadingErrorPopup.text = downloadError;
downloadingErrorPopup.open();
}
}
2023-04-18 21:10:06 -04:00
2023-06-22 15:44:49 -04:00
Label {
Layout.leftMargin: 20
textFormat: Text.StyledText
text: "<strong><font size=\"1\">"
+ (qsTr("Download size: ") + filesize)
+ "<br>"
+ (qsTr("RAM required: ") + (ramrequired > 0 ? ramrequired + " GB" : qsTr("minimal")))
+ "<br>"
+ (qsTr("Parameters: ") + parameters)
+ "<br>"
+ (qsTr("Quantization: ") + quant)
+ "<br>"
+ (qsTr("Type: ") + type)
+ "</strong></font>"
color: theme.textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
Accessible.role: Accessible.Paragraph
Accessible.name: text
Accessible.description: qsTr("Metadata about the model")
onLinkActivated: {
downloadingErrorPopup.text = downloadError;
downloadingErrorPopup.open();
}
}
2023-04-18 21:10:06 -04:00
2023-06-22 15:44:49 -04:00
Label {
visible: LLM.systemTotalRAMInGB() < ramrequired
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.maximumWidth: openaiKey.width
textFormat: Text.StyledText
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware.")
+ qsTr(" Model requires more memory (") + ramrequired
+ qsTr(" GB) than your system has available (")
+ LLM.systemTotalRAMInGBString() + ").</strong></font>"
color: theme.textErrorColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
wrapMode: Text.WordWrap
Accessible.role: Accessible.Paragraph
Accessible.name: text
Accessible.description: qsTr("Error for incompatible hardware")
onLinkActivated: {
downloadingErrorPopup.text = downloadError;
downloadingErrorPopup.open();
}
}
}
2023-04-24 00:14:52 -04:00
2023-06-22 15:44:49 -04:00
ColumnLayout {
visible: isDownloading && !calcHash
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: openaiKey.width
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
spacing: 20
ProgressBar {
id: itemProgressBar
Layout.fillWidth: true
width: openaiKey.width
value: bytesReceived / bytesTotal
background: Rectangle {
implicitHeight: 45
color: theme.progressBackground
2023-06-22 15:44:49 -04:00
radius: 3
}
contentItem: Item {
implicitHeight: 40
Rectangle {
width: itemProgressBar.visualPosition * parent.width
height: parent.height
radius: 2
color: theme.progressForeground
2023-06-22 15:44:49 -04:00
}
}
Accessible.role: Accessible.ProgressBar
Accessible.name: qsTr("Download progressBar")
Accessible.description: qsTr("Shows the progress made in the download")
}
2023-04-24 00:14:52 -04:00
2023-06-22 15:44:49 -04:00
Label {
id: speedLabel
color: theme.textColor
Layout.alignment: Qt.AlignRight
text: speed
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
Accessible.role: Accessible.Paragraph
Accessible.name: qsTr("Download speed")
Accessible.description: qsTr("Download speed in bytes/kilobytes/megabytes per second")
}
}
2023-04-18 21:10:06 -04:00
2023-06-22 15:44:49 -04:00
RowLayout {
visible: calcHash
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: openaiKey.width
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
Label {
id: calcHashLabel
color: theme.textColor
text: qsTr("Calculating MD5...")
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
Accessible.role: Accessible.Paragraph
Accessible.name: text
Accessible.description: qsTr("Whether the file hash is being calculated")
}
2023-06-22 15:44:49 -04:00
MyBusyIndicator {
id: busyCalcHash
running: calcHash
Accessible.role: Accessible.Animation
Accessible.name: qsTr("Busy indicator")
Accessible.description: qsTr("Displayed when the file hash is being calculated")
}
}
2023-06-22 15:44:49 -04:00
MyTextField {
id: openaiKey
visible: !installed && isChatGPT
Layout.topMargin: 20
Layout.leftMargin: 20
Layout.minimumWidth: 150
Layout.maximumWidth: textMetrics.width + 25
2023-06-22 15:44:49 -04:00
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
wrapMode: Text.WrapAnywhere
2023-06-22 15:44:49 -04:00
function showError() {
openaiKey.placeholderTextColor = theme.textErrorColor
}
onTextChanged: {
openaiKey.placeholderTextColor = theme.mutedTextColor
2023-06-22 15:44:49 -04:00
}
placeholderText: qsTr("enter $OPENAI_API_KEY")
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
}
2023-06-22 15:44:49 -04:00
}
}
}
2023-06-22 15:44:49 -04:00
Text {
id: descriptionText
text: description
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
2023-06-22 15:44:49 -04:00
Layout.row: 1
Layout.column: 0
Layout.leftMargin: 20
Layout.bottomMargin: 20
Layout.maximumWidth: modelListView.width - actionBox.width - 60
wrapMode: Text.WordWrap
textFormat: Text.StyledText
2023-05-16 09:32:01 -04:00
color: theme.textColor
2023-06-22 15:44:49 -04:00
linkColor: theme.textColor
2023-05-16 09:32:01 -04:00
Accessible.role: Accessible.Paragraph
2023-06-22 15:44:49 -04:00
Accessible.name: qsTr("Description")
Accessible.description: qsTr("File description")
2023-06-22 15:44:49 -04:00
onLinkActivated: Qt.openUrlExternally(link)
2023-05-16 09:32:01 -04:00
}
}
2023-06-22 15:44:49 -04:00
}
2023-04-18 21:10:06 -04:00
2023-06-22 15:44:49 -04:00
footer: Component {
Rectangle {
width: modelListView.width
height: expandButton.height + 80
color: ModelList.downloadableModels.count % 2 === 0 ? theme.darkContrast : theme.lightContrast
MySettingsButton {
2023-06-22 15:44:49 -04:00
id: expandButton
anchors.centerIn: parent
padding: 40
text: ModelList.downloadableModels.expanded ? qsTr("Show fewer models") : qsTr("Show more models")
onClicked: {
2023-06-22 15:44:49 -04:00
ModelList.downloadableModels.expanded = !ModelList.downloadableModels.expanded;
}
2023-04-18 21:10:06 -04:00
}
}
}
}
}
RowLayout {
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
spacing: 20
FolderDialog {
id: modelPathDialog
title: "Please choose a directory"
2023-07-09 11:31:01 -04:00
currentFolder: "file://" + MySettings.modelPath
onAccepted: {
2023-07-09 11:31:01 -04:00
MySettings.modelPath = selectedFolder
}
}
MySettingsLabel {
id: modelPathLabel
text: qsTr("Download path")
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
color: theme.textColor
Layout.row: 1
Layout.column: 0
}
MyDirectoryField {
id: modelPathDisplayField
text: MySettings.modelPath
2023-08-07 13:54:13 -04:00
font.pixelSize: theme.fontSizeLarge
Layout.fillWidth: true
ToolTip.text: qsTr("Path where model files will be downloaded to")
ToolTip.visible: hovered
Accessible.role: Accessible.ToolTip
Accessible.name: modelPathDisplayField.text
Accessible.description: ToolTip.text
onEditingFinished: {
if (isValid) {
2023-07-09 11:31:01 -04:00
MySettings.modelPath = modelPathDisplayField.text
} else {
text = MySettings.modelPath
}
}
}
MySettingsButton {
text: qsTr("Browse")
Accessible.description: qsTr("Choose where to save model files")
onClicked: modelPathDialog.open()
}
}
2023-04-18 21:10:06 -04:00
}
}