mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-06-24 14:32:03 +00:00
Always save chats to disk, but save them as text by default. This also changes
the UI behavior to always open a 'New Chat' and setting it as current instead of setting a restored chat as current. This improves usability by not requiring the user to wait if they want to immediately start chatting.
This commit is contained in:
parent
aed2068342
commit
908aec27fe
@ -385,7 +385,11 @@ bool Chat::serialize(QDataStream &stream, int version) const
|
|||||||
stream << m_modelInfo.filename();
|
stream << m_modelInfo.filename();
|
||||||
if (version > 2)
|
if (version > 2)
|
||||||
stream << m_collections;
|
stream << m_collections;
|
||||||
if (!m_llmodel->serialize(stream, version, true /*serializeKV*/))
|
|
||||||
|
const bool serializeKV = MySettings::globalInstance()->saveChatsContext();
|
||||||
|
if (version > 5)
|
||||||
|
stream << serializeKV;
|
||||||
|
if (!m_llmodel->serialize(stream, version, serializeKV))
|
||||||
return false;
|
return false;
|
||||||
if (!m_chatModel->serialize(stream, version))
|
if (!m_chatModel->serialize(stream, version))
|
||||||
return false;
|
return false;
|
||||||
@ -413,7 +417,6 @@ bool Chat::deserialize(QDataStream &stream, int version)
|
|||||||
if (!m_modelInfo.id().isEmpty())
|
if (!m_modelInfo.id().isEmpty())
|
||||||
emit modelInfoChanged();
|
emit modelInfoChanged();
|
||||||
|
|
||||||
bool deserializeKV = true; // make this a setting
|
|
||||||
bool discardKV = m_modelInfo.id().isEmpty();
|
bool discardKV = m_modelInfo.id().isEmpty();
|
||||||
|
|
||||||
// Prior to version 2 gptj models had a bug that fixed the kv_cache to F32 instead of F16 so
|
// Prior to version 2 gptj models had a bug that fixed the kv_cache to F32 instead of F16 so
|
||||||
@ -425,6 +428,11 @@ bool Chat::deserialize(QDataStream &stream, int version)
|
|||||||
stream >> m_collections;
|
stream >> m_collections;
|
||||||
emit collectionListChanged(m_collections);
|
emit collectionListChanged(m_collections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool deserializeKV = true;
|
||||||
|
if (version > 5)
|
||||||
|
stream >> deserializeKV;
|
||||||
|
|
||||||
m_llmodel->setModelInfo(m_modelInfo);
|
m_llmodel->setModelInfo(m_modelInfo);
|
||||||
if (!m_llmodel->deserialize(stream, version, deserializeKV, discardKV))
|
if (!m_llmodel->deserialize(stream, version, deserializeKV, discardKV))
|
||||||
return false;
|
return false;
|
||||||
|
@ -54,6 +54,8 @@ public:
|
|||||||
}
|
}
|
||||||
ChatModel *chatModel() { return m_chatModel; }
|
ChatModel *chatModel() { return m_chatModel; }
|
||||||
|
|
||||||
|
bool isNewChat() const { return m_name == tr("New Chat") && !m_chatModel->count(); }
|
||||||
|
|
||||||
Q_INVOKABLE void reset();
|
Q_INVOKABLE void reset();
|
||||||
Q_INVOKABLE void processSystemPrompt();
|
Q_INVOKABLE void processSystemPrompt();
|
||||||
Q_INVOKABLE bool isModelLoaded() const;
|
Q_INVOKABLE bool isModelLoaded() const;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
||||||
#define CHAT_FORMAT_MAGIC 0xF5D553CC
|
#define CHAT_FORMAT_MAGIC 0xF5D553CC
|
||||||
#define CHAT_FORMAT_VERSION 5
|
#define CHAT_FORMAT_VERSION 6
|
||||||
|
|
||||||
class MyChatListModel: public ChatListModel { };
|
class MyChatListModel: public ChatListModel { };
|
||||||
Q_GLOBAL_STATIC(MyChatListModel, chatListModelInstance)
|
Q_GLOBAL_STATIC(MyChatListModel, chatListModelInstance)
|
||||||
@ -17,11 +17,10 @@ ChatListModel *ChatListModel::globalInstance()
|
|||||||
ChatListModel::ChatListModel()
|
ChatListModel::ChatListModel()
|
||||||
: QAbstractListModel(nullptr)
|
: QAbstractListModel(nullptr)
|
||||||
, m_newChat(nullptr)
|
, m_newChat(nullptr)
|
||||||
, m_dummyChat(nullptr)
|
|
||||||
, m_serverChat(nullptr)
|
, m_serverChat(nullptr)
|
||||||
, m_currentChat(nullptr)
|
, m_currentChat(nullptr)
|
||||||
{
|
{
|
||||||
addDummyChat();
|
addChat();
|
||||||
|
|
||||||
ChatsRestoreThread *thread = new ChatsRestoreThread;
|
ChatsRestoreThread *thread = new ChatsRestoreThread;
|
||||||
connect(thread, &ChatsRestoreThread::chatRestored, this, &ChatListModel::restoreChat);
|
connect(thread, &ChatsRestoreThread::chatRestored, this, &ChatListModel::restoreChat);
|
||||||
@ -59,10 +58,7 @@ void ChatListModel::saveChats()
|
|||||||
for (Chat *chat : m_chats) {
|
for (Chat *chat : m_chats) {
|
||||||
if (chat == m_serverChat)
|
if (chat == m_serverChat)
|
||||||
continue;
|
continue;
|
||||||
const bool isChatGPT = chat->modelInfo().isChatGPT;
|
if (chat->isNewChat())
|
||||||
if (!isChatGPT && !MySettings::globalInstance()->saveChats())
|
|
||||||
continue;
|
|
||||||
if (isChatGPT && !MySettings::globalInstance()->saveChatGPTChats())
|
|
||||||
continue;
|
continue;
|
||||||
toSave.append(chat);
|
toSave.append(chat);
|
||||||
}
|
}
|
||||||
@ -249,35 +245,13 @@ void ChatListModel::restoreChat(Chat *chat)
|
|||||||
chat->setParent(this);
|
chat->setParent(this);
|
||||||
connect(chat, &Chat::nameChanged, this, &ChatListModel::nameChanged);
|
connect(chat, &Chat::nameChanged, this, &ChatListModel::nameChanged);
|
||||||
|
|
||||||
if (m_dummyChat) {
|
|
||||||
beginResetModel();
|
|
||||||
m_chats = QList<Chat*>({chat});
|
|
||||||
setCurrentChat(chat);
|
|
||||||
delete m_dummyChat;
|
|
||||||
m_dummyChat = nullptr;
|
|
||||||
endResetModel();
|
|
||||||
} else {
|
|
||||||
beginInsertRows(QModelIndex(), m_chats.size(), m_chats.size());
|
beginInsertRows(QModelIndex(), m_chats.size(), m_chats.size());
|
||||||
m_chats.append(chat);
|
m_chats.append(chat);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ChatListModel::chatsRestoredFinished()
|
void ChatListModel::chatsRestoredFinished()
|
||||||
{
|
{
|
||||||
if (m_dummyChat) {
|
|
||||||
beginResetModel();
|
|
||||||
Chat *dummy = m_dummyChat;
|
|
||||||
m_dummyChat = nullptr;
|
|
||||||
m_chats.clear();
|
|
||||||
addChat();
|
|
||||||
delete dummy;
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_chats.isEmpty())
|
|
||||||
addChat();
|
|
||||||
|
|
||||||
addServerChat();
|
addServerChat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public:
|
|||||||
Q_INVOKABLE void addChat()
|
Q_INVOKABLE void addChat()
|
||||||
{
|
{
|
||||||
// Don't add a new chat if we already have one
|
// Don't add a new chat if we already have one
|
||||||
if (m_newChat || m_dummyChat)
|
if (m_newChat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Create a new chat pointer and connect it to determine when it is populated
|
// Create a new chat pointer and connect it to determine when it is populated
|
||||||
@ -101,18 +101,6 @@ public:
|
|||||||
setCurrentChat(m_newChat);
|
setCurrentChat(m_newChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE void addDummyChat()
|
|
||||||
{
|
|
||||||
// Create a new dummy chat pointer and don't connect it
|
|
||||||
m_dummyChat = new Chat(this);
|
|
||||||
beginInsertRows(QModelIndex(), 0, 0);
|
|
||||||
m_chats.prepend(m_dummyChat);
|
|
||||||
endInsertRows();
|
|
||||||
emit countChanged();
|
|
||||||
m_currentChat = m_dummyChat;
|
|
||||||
emit currentChatChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_INVOKABLE void addServerChat()
|
Q_INVOKABLE void addServerChat()
|
||||||
{
|
{
|
||||||
// Create a new dummy chat pointer and don't connect it
|
// Create a new dummy chat pointer and don't connect it
|
||||||
@ -252,7 +240,6 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Chat* m_newChat;
|
Chat* m_newChat;
|
||||||
Chat* m_dummyChat;
|
|
||||||
Chat* m_serverChat;
|
Chat* m_serverChat;
|
||||||
Chat* m_currentChat;
|
Chat* m_currentChat;
|
||||||
QList<Chat*> m_chats;
|
QList<Chat*> m_chats;
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
static int default_threadCount = std::min(4, (int32_t) std::thread::hardware_concurrency());
|
static int default_threadCount = std::min(4, (int32_t) std::thread::hardware_concurrency());
|
||||||
static bool default_saveChats = false;
|
static bool default_saveChatsContext = false;
|
||||||
static bool default_saveChatGPTChats = true;
|
|
||||||
static bool default_serverChat = false;
|
static bool default_serverChat = false;
|
||||||
static QString default_userDefaultModel = "Application default";
|
static QString default_userDefaultModel = "Application default";
|
||||||
static bool default_forceMetal = false;
|
static bool default_forceMetal = false;
|
||||||
@ -103,8 +102,7 @@ void MySettings::restoreApplicationDefaults()
|
|||||||
setFontSize(default_fontSize);
|
setFontSize(default_fontSize);
|
||||||
setDevice(default_device);
|
setDevice(default_device);
|
||||||
setThreadCount(default_threadCount);
|
setThreadCount(default_threadCount);
|
||||||
setSaveChats(default_saveChats);
|
setSaveChatsContext(default_saveChatsContext);
|
||||||
setSaveChatGPTChats(default_saveChatGPTChats);
|
|
||||||
setServerChat(default_serverChat);
|
setServerChat(default_serverChat);
|
||||||
setModelPath(defaultLocalModelsPath());
|
setModelPath(defaultLocalModelsPath());
|
||||||
setUserDefaultModel(default_userDefaultModel);
|
setUserDefaultModel(default_userDefaultModel);
|
||||||
@ -397,40 +395,22 @@ void MySettings::setThreadCount(int c)
|
|||||||
emit threadCountChanged();
|
emit threadCountChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySettings::saveChats() const
|
bool MySettings::saveChatsContext() const
|
||||||
{
|
{
|
||||||
QSettings setting;
|
QSettings setting;
|
||||||
setting.sync();
|
setting.sync();
|
||||||
return setting.value("saveChats", default_saveChats).toBool();
|
return setting.value("saveChatsContext", default_saveChatsContext).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySettings::setSaveChats(bool b)
|
void MySettings::setSaveChatsContext(bool b)
|
||||||
{
|
{
|
||||||
if (saveChats() == b)
|
if (saveChatsContext() == b)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QSettings setting;
|
QSettings setting;
|
||||||
setting.setValue("saveChats", b);
|
setting.setValue("saveChatsContext", b);
|
||||||
setting.sync();
|
setting.sync();
|
||||||
emit saveChatsChanged();
|
emit saveChatsContextChanged();
|
||||||
}
|
|
||||||
|
|
||||||
bool MySettings::saveChatGPTChats() const
|
|
||||||
{
|
|
||||||
QSettings setting;
|
|
||||||
setting.sync();
|
|
||||||
return setting.value("saveChatGPTChats", default_saveChatGPTChats).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySettings::setSaveChatGPTChats(bool b)
|
|
||||||
{
|
|
||||||
if (saveChatGPTChats() == b)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QSettings setting;
|
|
||||||
setting.setValue("saveChatGPTChats", b);
|
|
||||||
setting.sync();
|
|
||||||
emit saveChatGPTChatsChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySettings::serverChat() const
|
bool MySettings::serverChat() const
|
||||||
|
@ -10,8 +10,7 @@ class MySettings : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int threadCount READ threadCount WRITE setThreadCount NOTIFY threadCountChanged)
|
Q_PROPERTY(int threadCount READ threadCount WRITE setThreadCount NOTIFY threadCountChanged)
|
||||||
Q_PROPERTY(bool saveChats READ saveChats WRITE setSaveChats NOTIFY saveChatsChanged)
|
Q_PROPERTY(bool saveChatsContext READ saveChatsContext WRITE setSaveChatsContext NOTIFY saveChatsContextChanged)
|
||||||
Q_PROPERTY(bool saveChatGPTChats READ saveChatGPTChats WRITE setSaveChatGPTChats NOTIFY saveChatGPTChatsChanged)
|
|
||||||
Q_PROPERTY(bool serverChat READ serverChat WRITE setServerChat NOTIFY serverChatChanged)
|
Q_PROPERTY(bool serverChat READ serverChat WRITE setServerChat NOTIFY serverChatChanged)
|
||||||
Q_PROPERTY(QString modelPath READ modelPath WRITE setModelPath NOTIFY modelPathChanged)
|
Q_PROPERTY(QString modelPath READ modelPath WRITE setModelPath NOTIFY modelPathChanged)
|
||||||
Q_PROPERTY(QString userDefaultModel READ userDefaultModel WRITE setUserDefaultModel NOTIFY userDefaultModelChanged)
|
Q_PROPERTY(QString userDefaultModel READ userDefaultModel WRITE setUserDefaultModel NOTIFY userDefaultModelChanged)
|
||||||
@ -64,10 +63,8 @@ public:
|
|||||||
// Application settings
|
// Application settings
|
||||||
int threadCount() const;
|
int threadCount() const;
|
||||||
void setThreadCount(int c);
|
void setThreadCount(int c);
|
||||||
bool saveChats() const;
|
bool saveChatsContext() const;
|
||||||
void setSaveChats(bool b);
|
void setSaveChatsContext(bool b);
|
||||||
bool saveChatGPTChats() const;
|
|
||||||
void setSaveChatGPTChats(bool b);
|
|
||||||
bool serverChat() const;
|
bool serverChat() const;
|
||||||
void setServerChat(bool b);
|
void setServerChat(bool b);
|
||||||
QString modelPath() const;
|
QString modelPath() const;
|
||||||
@ -122,8 +119,7 @@ Q_SIGNALS:
|
|||||||
void promptTemplateChanged(const ModelInfo &model);
|
void promptTemplateChanged(const ModelInfo &model);
|
||||||
void systemPromptChanged(const ModelInfo &model);
|
void systemPromptChanged(const ModelInfo &model);
|
||||||
void threadCountChanged();
|
void threadCountChanged();
|
||||||
void saveChatsChanged();
|
void saveChatsContextChanged();
|
||||||
void saveChatGPTChatsChanged();
|
|
||||||
void serverChatChanged();
|
void serverChatChanged();
|
||||||
void modelPathChanged();
|
void modelPathChanged();
|
||||||
void userDefaultModelChanged();
|
void userDefaultModelChanged();
|
||||||
|
@ -317,16 +317,6 @@ void Network::sendNetworkToggled(bool isActive)
|
|||||||
sendMixpanelEvent("network_toggled", QVector<KeyValue>{kv});
|
sendMixpanelEvent("network_toggled", QVector<KeyValue>{kv});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::sendSaveChatsToggled(bool isActive)
|
|
||||||
{
|
|
||||||
if (!MySettings::globalInstance()->networkUsageStatsActive())
|
|
||||||
return;
|
|
||||||
KeyValue kv;
|
|
||||||
kv.key = QString("isActive");
|
|
||||||
kv.value = QJsonValue(isActive);
|
|
||||||
sendMixpanelEvent("savechats_toggled", QVector<KeyValue>{kv});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Network::sendNewChat(int count)
|
void Network::sendNewChat(int count)
|
||||||
{
|
{
|
||||||
if (!MySettings::globalInstance()->networkUsageStatsActive())
|
if (!MySettings::globalInstance()->networkUsageStatsActive())
|
||||||
|
@ -38,7 +38,6 @@ public Q_SLOTS:
|
|||||||
void sendDownloadFinished(const QString &model, bool success);
|
void sendDownloadFinished(const QString &model, bool success);
|
||||||
Q_INVOKABLE void sendSettingsDialog();
|
Q_INVOKABLE void sendSettingsDialog();
|
||||||
Q_INVOKABLE void sendNetworkToggled(bool active);
|
Q_INVOKABLE void sendNetworkToggled(bool active);
|
||||||
Q_INVOKABLE void sendSaveChatsToggled(bool active);
|
|
||||||
Q_INVOKABLE void sendNewChat(int count);
|
Q_INVOKABLE void sendNewChat(int count);
|
||||||
Q_INVOKABLE void sendRemoveChat();
|
Q_INVOKABLE void sendRemoveChat();
|
||||||
Q_INVOKABLE void sendRenameChat();
|
Q_INVOKABLE void sendRenameChat();
|
||||||
|
@ -234,53 +234,35 @@ MySettingsTab {
|
|||||||
Accessible.description: ToolTip.text
|
Accessible.description: ToolTip.text
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
id: saveChatsLabel
|
id: saveChatsContextLabel
|
||||||
text: qsTr("Save chats to disk:")
|
text: qsTr("Save chats context to disk:")
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
Layout.row: 7
|
Layout.row: 7
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: saveChatsBox
|
id: saveChatsContextBox
|
||||||
Layout.row: 7
|
Layout.row: 7
|
||||||
Layout.column: 1
|
Layout.column: 1
|
||||||
checked: MySettings.saveChats
|
checked: MySettings.saveChatsContext
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Network.sendSaveChatsToggled(saveChatsBox.checked);
|
MySettings.saveChatsContext = !MySettings.saveChatsContext
|
||||||
MySettings.saveChats = !MySettings.saveChats
|
|
||||||
}
|
}
|
||||||
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
|
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
}
|
}
|
||||||
Label {
|
|
||||||
id: saveChatGPTChatsLabel
|
|
||||||
text: qsTr("Save ChatGPT chats to disk:")
|
|
||||||
color: theme.textColor
|
|
||||||
font.pixelSize: theme.fontSizeLarge
|
|
||||||
Layout.row: 8
|
|
||||||
Layout.column: 0
|
|
||||||
}
|
|
||||||
MyCheckBox {
|
|
||||||
id: saveChatGPTChatsBox
|
|
||||||
Layout.row: 8
|
|
||||||
Layout.column: 1
|
|
||||||
checked: MySettings.saveChatGPTChats
|
|
||||||
onClicked: {
|
|
||||||
MySettings.saveChatGPTChats = !MySettings.saveChatGPTChats
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Label {
|
Label {
|
||||||
id: serverChatLabel
|
id: serverChatLabel
|
||||||
text: qsTr("Enable API server:")
|
text: qsTr("Enable API server:")
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
Layout.row: 9
|
Layout.row: 8
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: serverChatBox
|
id: serverChatBox
|
||||||
Layout.row: 9
|
Layout.row: 8
|
||||||
Layout.column: 1
|
Layout.column: 1
|
||||||
checked: MySettings.serverChat
|
checked: MySettings.serverChat
|
||||||
onClicked: {
|
onClicked: {
|
||||||
@ -290,7 +272,7 @@ MySettingsTab {
|
|||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.row: 10
|
Layout.row: 9
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
Layout.columnSpan: 3
|
Layout.columnSpan: 3
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Loading…
Reference in New Issue
Block a user