mirror of
https://github.com/nomic-ai/gpt4all
synced 2024-11-02 09:40:42 +00:00
More extensive usage stats to help diagnose errors and problems in the ui.
This commit is contained in:
parent
f8c3ae6cc7
commit
db094c5b92
@ -64,6 +64,7 @@ qt_add_executable(chat
|
||||
download.h download.cpp
|
||||
network.h network.cpp
|
||||
llm.h llm.cpp
|
||||
sysinfo.h
|
||||
)
|
||||
|
||||
qt_add_qml_module(chat
|
||||
|
11
chat.cpp
11
chat.cpp
@ -18,6 +18,7 @@ Chat::Chat(QObject *parent)
|
||||
connect(m_llmodel, &ChatLLM::threadCountChanged, this, &Chat::threadCountChanged, Qt::QueuedConnection);
|
||||
connect(m_llmodel, &ChatLLM::threadCountChanged, this, &Chat::syncThreadCount, Qt::QueuedConnection);
|
||||
connect(m_llmodel, &ChatLLM::recalcChanged, this, &Chat::recalcChanged, Qt::QueuedConnection);
|
||||
connect(m_llmodel, &ChatLLM::recalcChanged, this, &Chat::handleRecalculating, Qt::QueuedConnection);
|
||||
connect(m_llmodel, &ChatLLM::generatedNameChanged, this, &Chat::generatedNameChanged, Qt::QueuedConnection);
|
||||
|
||||
connect(this, &Chat::promptRequested, m_llmodel, &ChatLLM::prompt, Qt::QueuedConnection);
|
||||
@ -37,7 +38,6 @@ Chat::Chat(QObject *parent)
|
||||
void Chat::reset()
|
||||
{
|
||||
stopGenerating();
|
||||
qDebug() << "reset blocking";
|
||||
emit resetContextRequested(); // blocking queued connection
|
||||
m_id = Network::globalInstance()->generateUniqueId();
|
||||
emit idChanged();
|
||||
@ -80,8 +80,10 @@ void Chat::responseStopped()
|
||||
{
|
||||
m_responseInProgress = false;
|
||||
emit responseInProgressChanged();
|
||||
if (m_llmodel->generatedName().isEmpty())
|
||||
if (m_llmodel->generatedName().isEmpty()) {
|
||||
Network::globalInstance()->sendChatStarted();
|
||||
emit generateNameRequested();
|
||||
}
|
||||
}
|
||||
|
||||
QString Chat::modelName() const
|
||||
@ -143,3 +145,8 @@ void Chat::generatedNameChanged()
|
||||
m_name = words.mid(0, wordCount).join(' ');
|
||||
emit nameChanged();
|
||||
}
|
||||
|
||||
void Chat::handleRecalculating()
|
||||
{
|
||||
Network::globalInstance()->sendRecalculatingContext(m_chatModel->count());
|
||||
}
|
||||
|
1
chat.h
1
chat.h
@ -79,6 +79,7 @@ private Q_SLOTS:
|
||||
void responseStarted();
|
||||
void responseStopped();
|
||||
void generatedNameChanged();
|
||||
void handleRecalculating();
|
||||
|
||||
private:
|
||||
ChatLLM *m_llmodel;
|
||||
|
@ -43,7 +43,6 @@ ChatLLM::ChatLLM()
|
||||
connect(&m_llmThread, &QThread::started, this, &ChatLLM::loadModel);
|
||||
connect(this, &ChatLLM::sendStartup, Network::globalInstance(), &Network::sendStartup);
|
||||
connect(this, &ChatLLM::sendModelLoaded, Network::globalInstance(), &Network::sendModelLoaded);
|
||||
connect(this, &ChatLLM::sendResetContext, Network::globalInstance(), &Network::sendResetContext);
|
||||
m_llmThread.setObjectName("llm thread"); // FIXME: Should identify these with chat name
|
||||
m_llmThread.start();
|
||||
}
|
||||
|
19
download.cpp
19
download.cpp
@ -1,4 +1,5 @@
|
||||
#include "download.h"
|
||||
#include "network.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QNetworkRequest>
|
||||
@ -202,6 +203,7 @@ void Download::downloadModel(const QString &modelFile)
|
||||
return;
|
||||
}
|
||||
|
||||
Network::globalInstance()->sendDownloadStarted(modelFile);
|
||||
QNetworkRequest request("http://gpt4all.io/models/" + modelFile);
|
||||
QSslConfiguration conf = request.sslConfiguration();
|
||||
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
@ -219,6 +221,8 @@ void Download::cancelDownload(const QString &modelFile)
|
||||
QNetworkReply *modelReply = m_activeDownloads.keys().at(i);
|
||||
QUrl url = modelReply->request().url();
|
||||
if (url.toString().endsWith(modelFile)) {
|
||||
Network::globalInstance()->sendDownloadCanceled(modelFile);
|
||||
|
||||
// Disconnect the signals
|
||||
disconnect(modelReply, &QNetworkReply::downloadProgress, this, &Download::handleDownloadProgress);
|
||||
disconnect(modelReply, &QNetworkReply::finished, this, &Download::handleModelDownloadFinished);
|
||||
@ -386,6 +390,20 @@ void Download::parseReleaseJsonFile(const QByteArray &jsonData)
|
||||
emit releaseInfoChanged();
|
||||
}
|
||||
|
||||
void Download::handleErrorOccurred(QNetworkReply::NetworkError code)
|
||||
{
|
||||
QNetworkReply *modelReply = qobject_cast<QNetworkReply *>(sender());
|
||||
if (!modelReply)
|
||||
return;
|
||||
|
||||
QString modelFilename = modelReply->url().fileName();
|
||||
qWarning() << "ERROR: Network error occurred attemptint to download"
|
||||
<< modelFilename
|
||||
<< "code:" << code
|
||||
<< "errorString" << modelReply->errorString();
|
||||
Network::globalInstance()->sendDownloadError(modelFilename, (int)code, modelReply->errorString());
|
||||
cancelDownload(modelFilename);
|
||||
}
|
||||
|
||||
void Download::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
@ -509,6 +527,7 @@ void Download::handleHashAndSaveFinished(bool success,
|
||||
// The hash and save should send back with tempfile closed
|
||||
Q_ASSERT(!tempFile->isOpen());
|
||||
QString modelFilename = modelReply->url().fileName();
|
||||
Network::globalInstance()->sendDownloadFinished(modelFilename, success);
|
||||
|
||||
ModelInfo info = m_modelMap.value(modelFilename);
|
||||
info.calcHash = false;
|
||||
|
@ -95,6 +95,7 @@ private Q_SLOTS:
|
||||
void handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
|
||||
void handleModelsJsonDownloadFinished();
|
||||
void handleReleaseJsonDownloadFinished();
|
||||
void handleErrorOccurred(QNetworkReply::NetworkError code);
|
||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleModelDownloadFinished();
|
||||
void handleHashAndSaveFinished(bool success,
|
||||
|
6
main.qml
6
main.qml
@ -290,9 +290,10 @@ Window {
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (Network.isActive)
|
||||
if (Network.isActive) {
|
||||
Network.isActive = false
|
||||
else
|
||||
Network.sendNetworkToggled(false);
|
||||
} else
|
||||
networkDialog.open()
|
||||
}
|
||||
}
|
||||
@ -472,6 +473,7 @@ Window {
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Network.sendResetContext(chatModel.count)
|
||||
currentChat.reset();
|
||||
}
|
||||
}
|
||||
|
140
network.cpp
140
network.cpp
@ -1,5 +1,6 @@
|
||||
#include "network.h"
|
||||
#include "llm.h"
|
||||
#include "sysinfo.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QGuiApplication>
|
||||
@ -13,7 +14,7 @@
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <sys/sysctl.h>
|
||||
std::string getCPUModel() {
|
||||
char buffer[256];
|
||||
@ -204,11 +205,15 @@ void Network::sendModelLoaded()
|
||||
sendMixpanelEvent("model_load");
|
||||
}
|
||||
|
||||
void Network::sendResetContext()
|
||||
void Network::sendResetContext(int conversationLength)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("reset_context");
|
||||
|
||||
KeyValue kv;
|
||||
kv.key = QString("length");
|
||||
kv.value = QJsonValue(conversationLength);
|
||||
sendMixpanelEvent("reset_context", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendStartup()
|
||||
@ -228,7 +233,122 @@ void Network::sendCheckForUpdates()
|
||||
sendMixpanelEvent("check_for_updates");
|
||||
}
|
||||
|
||||
void Network::sendMixpanelEvent(const QString &ev)
|
||||
void Network::sendModelDownloaderDialog()
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("download_dialog");
|
||||
}
|
||||
|
||||
void Network::sendDownloadStarted(const QString &model)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("model");
|
||||
kv.value = QJsonValue(model);
|
||||
sendMixpanelEvent("download_started", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendDownloadCanceled(const QString &model)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("model");
|
||||
kv.value = QJsonValue(model);
|
||||
sendMixpanelEvent("download_canceled", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendDownloadError(const QString &model, int code, const QString &errorString)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("model");
|
||||
kv.value = QJsonValue(model);
|
||||
KeyValue kvCode;
|
||||
kvCode.key = QString("code");
|
||||
kvCode.value = QJsonValue(code);
|
||||
KeyValue kvError;
|
||||
kvError.key = QString("error");
|
||||
kvError.value = QJsonValue(errorString);
|
||||
sendMixpanelEvent("download_error", QVector<KeyValue>{kv, kvCode, kvError});
|
||||
}
|
||||
|
||||
void Network::sendDownloadFinished(const QString &model, bool success)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("model");
|
||||
kv.value = QJsonValue(model);
|
||||
KeyValue kvSuccess;
|
||||
kvSuccess.key = QString("success");
|
||||
kvSuccess.value = QJsonValue(success);
|
||||
sendMixpanelEvent("download_finished", QVector<KeyValue>{kv, kvSuccess});
|
||||
}
|
||||
|
||||
void Network::sendSettingsDialog()
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("settings_dialog");
|
||||
}
|
||||
|
||||
void Network::sendNetworkToggled(bool isActive)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("isActive");
|
||||
kv.value = QJsonValue(isActive);
|
||||
sendMixpanelEvent("network_toggled", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendNewChat(int count)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
KeyValue kv;
|
||||
kv.key = QString("number_of_chats");
|
||||
kv.value = QJsonValue(count);
|
||||
sendMixpanelEvent("new_chat", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendRemoveChat()
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("remove_chat");
|
||||
}
|
||||
|
||||
void Network::sendRenameChat()
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("rename_chat");
|
||||
}
|
||||
|
||||
void Network::sendChatStarted()
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
sendMixpanelEvent("chat_started");
|
||||
}
|
||||
|
||||
void Network::sendRecalculatingContext(int conversationLength)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
|
||||
KeyValue kv;
|
||||
kv.key = QString("length");
|
||||
kv.value = QJsonValue(conversationLength);
|
||||
sendMixpanelEvent("recalc_context", QVector<KeyValue>{kv});
|
||||
}
|
||||
|
||||
void Network::sendMixpanelEvent(const QString &ev, const QVector<KeyValue> &values)
|
||||
{
|
||||
if (!m_usageStatsActive)
|
||||
return;
|
||||
@ -250,16 +370,20 @@ void Network::sendMixpanelEvent(const QString &ev)
|
||||
if (ev == "startup") {
|
||||
const QSize display = QGuiApplication::primaryScreen()->size();
|
||||
properties.insert("display", QString("%1x%2").arg(display.width()).arg(display.height()));
|
||||
properties.insert("ram", getSystemTotalRAM());
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
properties.insert("avx", __builtin_cpu_supports("avx"));
|
||||
properties.insert("avx2", __builtin_cpu_supports("avx2"));
|
||||
properties.insert("fma", __builtin_cpu_supports("fma"));
|
||||
properties.insert("avx", bool(__builtin_cpu_supports("avx")));
|
||||
properties.insert("avx2", bool(__builtin_cpu_supports("avx2")));
|
||||
properties.insert("fma", bool(__builtin_cpu_supports("fma")));
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#if defined(Q_OS_MAC)
|
||||
properties.insert("cpu", QString::fromStdString(getCPUModel()));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (auto p : values)
|
||||
properties.insert(p.key, p.value);
|
||||
|
||||
QJsonObject event;
|
||||
event.insert("event", ev);
|
||||
event.insert("properties", properties);
|
||||
|
22
network.h
22
network.h
@ -4,6 +4,12 @@
|
||||
#include <QObject>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonValue>
|
||||
|
||||
struct KeyValue {
|
||||
QString key;
|
||||
QJsonValue value;
|
||||
};
|
||||
|
||||
class Network : public QObject
|
||||
{
|
||||
@ -31,9 +37,21 @@ Q_SIGNALS:
|
||||
public Q_SLOTS:
|
||||
void sendOptOut();
|
||||
void sendModelLoaded();
|
||||
void sendResetContext();
|
||||
void sendStartup();
|
||||
void sendCheckForUpdates();
|
||||
Q_INVOKABLE void sendModelDownloaderDialog();
|
||||
Q_INVOKABLE void sendResetContext(int conversationLength);
|
||||
void sendDownloadStarted(const QString &model);
|
||||
void sendDownloadCanceled(const QString &model);
|
||||
void sendDownloadError(const QString &model, int code, const QString &errorString);
|
||||
void sendDownloadFinished(const QString &model, bool success);
|
||||
Q_INVOKABLE void sendSettingsDialog();
|
||||
Q_INVOKABLE void sendNetworkToggled(bool active);
|
||||
Q_INVOKABLE void sendNewChat(int count);
|
||||
Q_INVOKABLE void sendRemoveChat();
|
||||
Q_INVOKABLE void sendRenameChat();
|
||||
void sendChatStarted();
|
||||
void sendRecalculatingContext(int conversationLength);
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleIpifyFinished();
|
||||
@ -45,7 +63,7 @@ private Q_SLOTS:
|
||||
private:
|
||||
void sendHealth();
|
||||
void sendIpify();
|
||||
void sendMixpanelEvent(const QString &event);
|
||||
void sendMixpanelEvent(const QString &event, const QVector<KeyValue> &values = QVector<KeyValue>());
|
||||
void sendMixpanel(const QByteArray &json, bool isOptOut = false);
|
||||
bool packageAndSendJson(const QString &ingestId, const QString &json);
|
||||
|
||||
|
@ -55,6 +55,7 @@ Drawer {
|
||||
}
|
||||
onClicked: {
|
||||
LLM.chatListModel.addChat();
|
||||
Network.sendNewChat(LLM.chatListModel.count)
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,11 +111,9 @@ Drawer {
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
Keys.onReturnPressed: (event)=> {
|
||||
changeName();
|
||||
}
|
||||
onEditingFinished: {
|
||||
changeName();
|
||||
Network.sendRenameChat()
|
||||
}
|
||||
function changeName() {
|
||||
LLM.chatListModel.get(index).name = chatName.text
|
||||
@ -209,6 +208,7 @@ Drawer {
|
||||
}
|
||||
onClicked: {
|
||||
LLM.chatListModel.removeChat(LLM.chatListModel.get(index))
|
||||
Network.sendRemoveChat()
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Confirm delete of the chat")
|
||||
|
@ -6,6 +6,7 @@ import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
import download
|
||||
import llm
|
||||
import network
|
||||
|
||||
Dialog {
|
||||
id: modelDownloaderDialog
|
||||
@ -23,6 +24,10 @@ Dialog {
|
||||
radius: 10
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
Network.sendModelDownloaderDialog();
|
||||
}
|
||||
|
||||
property string defaultModelPath: Download.defaultLocalModelsPath()
|
||||
property alias modelPath: settings.modelPath
|
||||
Settings {
|
||||
|
@ -161,10 +161,16 @@ NOTE: By turning on this feature, you will be sending your data to the GPT4All O
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (Network.isActive)
|
||||
return
|
||||
Network.isActive = true;
|
||||
Network.sendNetworkToggled(true);
|
||||
}
|
||||
|
||||
onRejected: {
|
||||
if (!Network.isActive)
|
||||
return
|
||||
Network.isActive = false;
|
||||
Network.sendNetworkToggled(false);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,10 @@ Dialog {
|
||||
radius: 10
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
Network.sendSettingsDialog();
|
||||
}
|
||||
|
||||
Theme {
|
||||
id: theme
|
||||
}
|
||||
|
48
sysinfo.h
Normal file
48
sysinfo.h
Normal file
@ -0,0 +1,48 @@
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
QString getSystemTotalRAM()
|
||||
{
|
||||
qint64 totalRAM = 0;
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
QFile file("/proc/meminfo");
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&file);
|
||||
QString line = in.readLine();
|
||||
while (!line.isNull()) {
|
||||
if (line.startsWith("MemTotal")) {
|
||||
QStringList parts = line.split(QRegularExpression("\\s+"));
|
||||
totalRAM = parts[1].toLongLong() * 1024; // Convert from KB to bytes
|
||||
break;
|
||||
}
|
||||
line = in.readLine();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
#elif defined(Q_OS_MAC)
|
||||
int mib[2] = {CTL_HW, HW_MEMSIZE};
|
||||
size_t length = sizeof(totalRAM);
|
||||
sysctl(mib, 2, &totalRAM, &length, NULL, 0);
|
||||
#elif defined(Q_OS_WIN)
|
||||
MEMORYSTATUSEX memoryStatus;
|
||||
memoryStatus.dwLength = sizeof(memoryStatus);
|
||||
GlobalMemoryStatusEx(&memoryStatus);
|
||||
totalRAM = memoryStatus.ullTotalPhys;
|
||||
#endif
|
||||
|
||||
double totalRAM_GB = static_cast<double>(totalRAM) / (1024 * 1024 * 1024);
|
||||
return QString::number(totalRAM_GB, 'f', 2) + " GB";
|
||||
}
|
Loading…
Reference in New Issue
Block a user