Add more of the UI for selecting collections for chats.

This commit is contained in:
Adam Treat 2023-05-23 14:51:14 -04:00 committed by AT
parent 2827c5876c
commit 01b8c7617f
8 changed files with 182 additions and 9 deletions

View File

@ -77,6 +77,7 @@ qt_add_qml_module(chat
QML_FILES
main.qml
qml/ChatDrawer.qml
qml/CollectionsDialog.qml
qml/LocalDocs.qml
qml/ModelDownloaderDialog.qml
qml/NetworkDialog.qml
@ -96,6 +97,7 @@ qt_add_qml_module(chat
icons/stop_generating.svg
icons/regenerate.svg
icons/copy.svg
icons/db.svg
icons/settings.svg
icons/edit.svg
icons/trash.svg

View File

@ -116,7 +116,7 @@ void Chat::prompt(const QString &prompt, const QString &prompt_template, int32_t
m_queuedPrompt.n_batch = n_batch;
m_queuedPrompt.repeat_penalty = repeat_penalty;
m_queuedPrompt.repeat_penalty_tokens = repeat_penalty_tokens;
LocalDocs::globalInstance()->requestRetrieve(QList<QString>("localdocs"), prompt);
LocalDocs::globalInstance()->requestRetrieve(m_collections, prompt);
}
void Chat::handleLocalDocsRetrieved()
@ -162,9 +162,9 @@ QString Chat::responseState() const
{
switch (m_responseState) {
case ResponseStopped: return QStringLiteral("response stopped");
case LocalDocsRetrieval: return QStringLiteral("retrieving localdocs");
case LocalDocsProcessing: return QStringLiteral("processing localdocs");
case PromptProcessing: return QStringLiteral("processing prompt");
case LocalDocsRetrieval: return QStringLiteral("retrieving ") + m_collections.join(", ");
case LocalDocsProcessing: return QStringLiteral("processing ") + m_collections.join(", ");
case PromptProcessing: return QStringLiteral("processing");
case ResponseGeneration: return QStringLiteral("generating response");
};
Q_UNREACHABLE();
@ -397,3 +397,31 @@ QList<QString> Chat::modelList() const
return list;
}
QList<QString> Chat::collectionList() const
{
return m_collections;
}
bool Chat::hasCollection(const QString &collection) const
{
return m_collections.contains(collection);
}
void Chat::addCollection(const QString &collection)
{
if (hasCollection(collection))
return;
m_collections.append(collection);
emit collectionListChanged();
}
void Chat::removeCollection(const QString &collection)
{
if (!hasCollection(collection))
return;
m_collections.removeAll(collection);
emit collectionListChanged();
}

View File

@ -23,6 +23,7 @@ class Chat : public QObject
Q_PROPERTY(QList<QString> modelList READ modelList NOTIFY modelListChanged)
Q_PROPERTY(bool isServer READ isServer NOTIFY isServerChanged)
Q_PROPERTY(QString responseState READ responseState NOTIFY responseStateChanged)
Q_PROPERTY(QList<QString> collectionList READ collectionList NOTIFY collectionListChanged)
QML_ELEMENT
QML_UNCREATABLE("Only creatable from c++!")
@ -78,6 +79,12 @@ public:
QList<QString> modelList() const;
bool isServer() const { return m_isServer; }
QList<QString> collectionList() const;
Q_INVOKABLE bool hasCollection(const QString &collection) const;
Q_INVOKABLE void addCollection(const QString &collection);
Q_INVOKABLE void removeCollection(const QString &collection);
public Q_SLOTS:
void serverNewPromptResponsePair(const QString &prompt);
@ -104,6 +111,7 @@ Q_SIGNALS:
void modelListChanged();
void modelLoadingError(const QString &error);
void isServerChanged();
void collectionListChanged();
private Q_SLOTS:
void handleLocalDocsRetrieved();
@ -132,6 +140,7 @@ private:
QString m_name;
QString m_userName;
QString m_savedModelName;
QList<QString> m_collections;
ChatModel *m_chatModel;
bool m_responseInProgress;
ResponseState m_responseState;

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="#7d7d8e" viewBox="0 0 448 512"><path d="M448 80v48c0 44.2-100.3 80-224 80S0 172.2 0 128V80C0 35.8 100.3 0 224 0S448 35.8 448 80zM393.2 214.7c20.8-7.4 39.9-16.9 54.8-28.6V288c0 44.2-100.3 80-224 80S0 332.2 0 288V186.1c14.9 11.8 34 21.2 54.8 28.6C99.7 230.7 159.5 240 224 240s124.3-9.3 169.2-25.3zM0 346.1c14.9 11.8 34 21.2 54.8 28.6C99.7 390.7 159.5 400 224 400s124.3-9.3 169.2-25.3c20.8-7.4 39.9-16.9 54.8-28.6V432c0 44.2-100.3 80-224 80S0 476.2 0 432V346.1z"/></svg>
<!--
Font Awesome Free 5.2.0 by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
-->

After

Width:  |  Height:  |  Size: 689 B

View File

@ -290,9 +290,53 @@ Window {
}
}
CollectionsDialog {
id: collectionsDialog
anchors.centerIn: parent
}
Button {
id: collectionsButton
anchors.right: networkButton.left
anchors.top: parent.top
anchors.topMargin: 30
anchors.rightMargin: 30
width: 40
height: 40
z: 200
padding: 15
background: Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "transparent"
visible: currentChat.collectionList.length
border.color: theme.backgroundLightest
border.width: 1
radius: 10
}
Image {
anchors.centerIn: parent
mipmap: true
width: 25
height: 25
source: "qrc:/gpt4all/icons/db.svg"
}
}
Accessible.role: Accessible.Button
Accessible.name: qsTr("Add collections of documents to the chat")
Accessible.description: qsTr("Provides a button to add collections of documents to the chat")
onClicked: {
collectionsDialog.open()
}
}
Button {
id: settingsButton
anchors.right: networkButton.left
anchors.right: collectionsButton.left
anchors.top: parent.top
anchors.topMargin: 30
anchors.rightMargin: 30

View File

@ -0,0 +1,86 @@
import QtCore
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Basic
import QtQuick.Layouts
import QtQuick.Dialogs
import localdocs
import llm
Dialog {
id: collectionsDialog
modal: true
opacity: 0.9
padding: 20
width: 480
height: 640
property var currentChat: LLM.chatListModel.currentChat
background: Rectangle {
anchors.fill: parent
color: theme.backgroundDarkest
border.width: 1
border.color: theme.dialogBorder
radius: 10
}
Label {
id: listLabel
anchors.top: parent.top
anchors.left: parent.left
text: "Available Collections:"
color: theme.textColor
}
ScrollView {
id: scrollView
anchors.top: listLabel.bottom
anchors.topMargin: 20
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
clip: true
contentHeight: 300
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
background: Rectangle {
color: theme.backgroundLighter
}
ListView {
id: listView
model: LocalDocs.localDocsModel
boundsBehavior: Flickable.StopAtBounds
delegate: Rectangle {
id: item
width: listView.width
height: collectionId.height + 40
color: index % 2 === 0 ? theme.backgroundLight : theme.backgroundLighter
MyCheckBox {
id: checkBox
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.margins: 20
checked: currentChat.hasCollection(collection)
onClicked: {
if (checkBox.checked) {
currentChat.addCollection(collection)
} else {
currentChat.removeCollection(collection)
}
}
}
Text {
id: collectionId
anchors.verticalCenter: parent.verticalCenter
anchors.left: checkBox.right
anchors.margins: 20
text: collection
elide: Text.ElideRight
color: theme.textColor
}
}
}
}
}

View File

@ -186,7 +186,7 @@ Item {
id: chunkSizeTextField
Layout.row: 0
Layout.column: 1
ToolTip.text: qsTr("Number of characters per document snippet. NOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
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
}
@ -201,7 +201,7 @@ Item {
MyTextField {
Layout.row: 1
Layout.column: 1
ToolTip.text: qsTr("Best N matches of retrieved document snippets to add to the context for prompt. NOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.text: qsTr("Best N matches of retrieved document snippets to add to the context for prompt.\nNOTE: larger numbers increase likelihood of factual responses, but also result in slower generation.")
ToolTip.visible: hovered
}

View File

@ -225,8 +225,7 @@ Dialog {
contentItem: IconLabel {
color: theme.textColor
font.bold: localDocsButton.checked
font.pixelSize: localDocsButton.checked ? theme.fontSizeLarger : theme.fontSizeLarge
text: qsTr("Local Docs Plugin")
text: qsTr("LocalDocs Plugin (BETA)")
}
background: Rectangle {
color: localDocsButton.checked ? theme.backgroundDarkest : theme.backgroundLight