2023-06-28 23:46:03 -04:00
import QtCore
import QtQuick
import QtQuick . Controls
import QtQuick . Controls . Basic
import QtQuick . Layouts
import QtQuick . Dialogs
import localdocs
2023-10-24 12:13:32 -04:00
import modellist
2023-06-28 23:46:03 -04:00
import mysettings
2023-07-01 11:34:21 -04:00
import network
2023-06-28 23:46:03 -04:00
MySettingsTab {
2023-07-01 11:34:21 -04:00
onRestoreDefaultsClicked: {
MySettings . restoreLocalDocsDefaults ( ) ;
}
2023-10-24 12:13:32 -04:00
property bool hasEmbeddingModel: ModelList . embeddingModels . count !== 0
showAdvancedSettingsButton: hasEmbeddingModel
showRestoreDefaultsButton: hasEmbeddingModel
title: qsTr ( "LocalDocs" )
2023-06-28 23:46:03 -04:00
contentItem: ColumnLayout {
id: root
spacing: 10
property alias collection: collection . text
property alias folder_path: folderEdit . text
2023-10-24 12:13:32 -04:00
Label {
id: downloadLabel
Layout.fillWidth: true
Layout.maximumWidth: parent . width
wrapMode: Text . Wrap
visible: ! hasEmbeddingModel
Layout.alignment: Qt . AlignLeft
text: qsTr ( "This feature requires the download of a text embedding model in order to index documents for later search. Please download the <b>SBert</a> text embedding model from the download dialog to proceed." )
font.pixelSize: theme . fontSizeLarger
}
MyButton {
visible: ! hasEmbeddingModel
Layout.topMargin: 20
Layout.alignment: Qt . AlignLeft
text: qsTr ( "Download" )
font.pixelSize: theme . fontSizeLarger
onClicked: {
downloadClicked ( )
}
}
2023-07-01 11:34:21 -04:00
Item {
2023-10-24 12:13:32 -04:00
visible: hasEmbeddingModel
2023-06-28 23:46:03 -04:00
Layout.fillWidth: true
2023-07-01 11:34:21 -04:00
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
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-07-01 11:34:21 -04:00
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
}
2023-06-28 23:46:03 -04:00
}
2023-07-01 11:34:21 -04:00
MyDirectoryField {
id: folderEdit
Layout.fillWidth: true
text: root . folder_path
placeholderText: qsTr ( "Folder path..." )
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-07-01 11:34:21 -04:00
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
}
2023-06-28 23:46:03 -04:00
}
2023-07-01 11:34:21 -04:00
MyButton {
id: browseButton
text: qsTr ( "Browse" )
onClicked: {
2023-07-09 13:05:06 -04:00
openFolderDialog ( StandardPaths . writableLocation ( StandardPaths . HomeLocation ) , function ( selectedFolder ) {
root . folder_path = selectedFolder
} )
2023-07-01 11:34:21 -04:00
}
2023-06-28 23:46:03 -04:00
}
2023-07-01 11:34:21 -04:00
MyButton {
id: addButton
text: qsTr ( "Add" )
Accessible.role: Accessible . Button
Accessible.name: text
2023-10-21 10:38:46 -04:00
Accessible.description: qsTr ( "Add collection" )
2023-07-01 11:34:21 -04:00
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 ( )
2023-06-28 23:46:03 -04:00
}
}
}
}
2023-07-01 11:34:21 -04:00
ColumnLayout {
2023-10-24 12:13:32 -04:00
visible: hasEmbeddingModel
2023-07-01 11:34:21 -04:00
spacing: 0
Repeater {
2023-06-28 23:46:03 -04:00
model: LocalDocs . localDocsModel
delegate: Rectangle {
id: item
2023-07-01 11:34:21 -04:00
Layout.fillWidth: true
2023-06-28 23:46:03 -04:00
height: buttons . height + 20
2023-07-01 11:34:21 -04:00
color: index % 2 === 0 ? theme.backgroundDark : theme . backgroundDarker
2023-06-28 23:46:03 -04:00
property bool removing: false
Text {
id: collectionId
anchors.verticalCenter: parent . verticalCenter
anchors.left: parent . left
anchors.margins: 20
text: collection
elide: Text . ElideRight
color: theme . textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-06-28 23:46:03 -04:00
width: 200
}
Text {
id: folderId
anchors.left: collectionId . right
2023-07-01 11:34:21 -04:00
anchors.right: buttons . left
2023-06-28 23:46:03 -04:00
anchors.margins: 20
anchors.verticalCenter: parent . verticalCenter
text: folder_path
elide: Text . ElideRight
color: theme . textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-06-28 23:46:03 -04:00
}
Item {
id: buttons
anchors.right: parent . right
anchors.verticalCenter: parent . verticalCenter
anchors.margins: 20
2023-10-24 12:13:32 -04:00
width: removeButton . width
height: removeButton . height
2023-06-28 23:46:03 -04:00
MyButton {
id: removeButton
anchors.centerIn: parent
text: qsTr ( "Remove" )
2023-10-24 12:13:32 -04:00
visible: ! item . removing
2023-06-28 23:46:03 -04:00
onClicked: {
item . removing = true
LocalDocs . removeFolder ( collection , folder_path )
}
}
}
}
}
}
2023-07-05 19:41:07 -04:00
RowLayout {
2023-10-24 12:13:32 -04:00
visible: hasEmbeddingModel
2023-07-05 19:41:07 -04:00
Label {
id: showReferencesLabel
text: qsTr ( "Show references:" )
color: theme . textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-07-05 19:41:07 -04:00
}
MyCheckBox {
id: showReferencesBox
checked: MySettings . localDocsShowReferences
onClicked: {
MySettings . localDocsShowReferences = ! MySettings . localDocsShowReferences
}
ToolTip.text: qsTr ( "Shows any references in GUI generated by localdocs" )
ToolTip.visible: hovered
}
}
2023-07-01 11:34:21 -04:00
Rectangle {
2023-10-24 12:13:32 -04:00
visible: hasEmbeddingModel
2023-06-28 23:46:03 -04:00
Layout.fillWidth: true
2023-07-01 11:34:21 -04:00
height: 1
color: theme . tabBorder
}
}
advancedSettings: GridLayout {
id: gridLayout
columns: 3
rowSpacing: 10
columnSpacing: 10
2023-10-24 12:13:32 -04:00
visible: hasEmbeddingModel
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
Rectangle {
Layout.row: 3
Layout.column: 0
Layout.fillWidth: true
Layout.columnSpan: 3
height: 1
color: theme . tabBorder
}
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
Label {
id: chunkLabel
Layout.row: 1
Layout.column: 0
color: theme . textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-07-01 11:34:21 -04:00
text: qsTr ( "Document snippet size (characters):" )
}
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
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
2023-06-28 23:46:03 -04:00
}
2023-07-01 11:34:21 -04:00
onEditingFinished: {
var val = parseInt ( text )
if ( ! isNaN ( val ) ) {
MySettings . localDocsChunkSize = val
focus = false
} else {
text = MySettings . localDocsChunkSize
2023-06-28 23:46:03 -04:00
}
}
2023-07-01 11:34:21 -04:00
}
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
Label {
id: contextItemsPerPrompt
Layout.row: 2
Layout.column: 0
color: theme . textColor
2023-08-07 13:54:13 -04:00
font.pixelSize: theme . fontSizeLarge
2023-10-06 14:38:42 -04:00
text: qsTr ( "Max document snippets per prompt:" )
2023-07-01 11:34:21 -04:00
}
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
MyTextField {
Layout.row: 2
Layout.column: 1
2023-10-06 14:38:42 -04:00
ToolTip.text: qsTr ( "Max 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." )
2023-07-01 11:34:21 -04:00
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
2023-06-28 23:46:03 -04:00
}
}
2023-07-01 11:34:21 -04:00
}
2023-06-28 23:46:03 -04:00
2023-07-01 11:34:21 -04:00
Item {
Layout.row: 1
Layout.column: 2
Layout.rowSpan: 2
Layout.fillWidth: true
Layout.alignment: Qt . AlignTop
Layout.minimumHeight: warningLabel . height
2023-06-28 23:46:03 -04:00
Label {
id: warningLabel
2023-07-01 11:34:21 -04:00
width: parent . width
2023-06-28 23:46:03 -04:00
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 ) }
}
}
}
}