mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-08-14 06:05:34 +00:00
Initial support for opt-in telemetry.
This commit is contained in:
parent
a3d97fa009
commit
ee5c58c26c
20
llm.cpp
20
llm.cpp
@ -1,5 +1,6 @@
|
|||||||
#include "llm.h"
|
#include "llm.h"
|
||||||
#include "download.h"
|
#include "download.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -43,6 +44,9 @@ LLMObject::LLMObject()
|
|||||||
{
|
{
|
||||||
moveToThread(&m_llmThread);
|
moveToThread(&m_llmThread);
|
||||||
connect(&m_llmThread, &QThread::started, this, &LLMObject::loadModel);
|
connect(&m_llmThread, &QThread::started, this, &LLMObject::loadModel);
|
||||||
|
connect(this, &LLMObject::sendStartup, Network::globalInstance(), &Network::sendStartup);
|
||||||
|
connect(this, &LLMObject::sendModelLoaded, Network::globalInstance(), &Network::sendModelLoaded);
|
||||||
|
connect(this, &LLMObject::sendResetContext, Network::globalInstance(), &Network::sendResetContext);
|
||||||
m_llmThread.setObjectName("llm thread");
|
m_llmThread.setObjectName("llm thread");
|
||||||
m_llmThread.start();
|
m_llmThread.start();
|
||||||
}
|
}
|
||||||
@ -65,11 +69,14 @@ bool LLMObject::loadModelPrivate(const QString &modelName)
|
|||||||
if (isModelLoaded() && m_modelName == modelName)
|
if (isModelLoaded() && m_modelName == modelName)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
bool isFirstLoad = false;
|
||||||
if (isModelLoaded()) {
|
if (isModelLoaded()) {
|
||||||
resetContext();
|
resetContextPrivate();
|
||||||
delete m_llmodel;
|
delete m_llmodel;
|
||||||
m_llmodel = nullptr;
|
m_llmodel = nullptr;
|
||||||
emit isModelLoadedChanged();
|
emit isModelLoadedChanged();
|
||||||
|
} else {
|
||||||
|
isFirstLoad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isGPTJ = false;
|
bool isGPTJ = false;
|
||||||
@ -93,6 +100,11 @@ bool LLMObject::loadModelPrivate(const QString &modelName)
|
|||||||
|
|
||||||
emit isModelLoadedChanged();
|
emit isModelLoadedChanged();
|
||||||
emit threadCountChanged();
|
emit threadCountChanged();
|
||||||
|
|
||||||
|
if (isFirstLoad)
|
||||||
|
emit sendStartup();
|
||||||
|
else
|
||||||
|
emit sendModelLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_llmodel)
|
if (m_llmodel)
|
||||||
@ -141,6 +153,12 @@ void LLMObject::resetResponse()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LLMObject::resetContext()
|
void LLMObject::resetContext()
|
||||||
|
{
|
||||||
|
resetContextPrivate();
|
||||||
|
emit sendResetContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLMObject::resetContextPrivate()
|
||||||
{
|
{
|
||||||
regenerateResponse();
|
regenerateResponse();
|
||||||
s_ctx = LLModel::PromptContext();
|
s_ctx = LLModel::PromptContext();
|
||||||
|
4
llm.h
4
llm.h
@ -51,8 +51,12 @@ Q_SIGNALS:
|
|||||||
void modelListChanged();
|
void modelListChanged();
|
||||||
void threadCountChanged();
|
void threadCountChanged();
|
||||||
void recalcChanged();
|
void recalcChanged();
|
||||||
|
void sendStartup();
|
||||||
|
void sendModelLoaded();
|
||||||
|
void sendResetContext();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void resetContextPrivate();
|
||||||
bool loadModelPrivate(const QString &modelName);
|
bool loadModelPrivate(const QString &modelName);
|
||||||
bool handleResponse(int32_t token, const std::string &response);
|
bool handleResponse(int32_t token, const std::string &response);
|
||||||
bool handleRecalculate(bool isRecalc);
|
bool handleRecalculate(bool isRecalc);
|
||||||
|
@ -44,7 +44,7 @@ add_library(llmodel
|
|||||||
gptj.h gptj.cpp
|
gptj.h gptj.cpp
|
||||||
llamamodel.h llamamodel.cpp
|
llamamodel.h llamamodel.cpp
|
||||||
llama.cpp/examples/common.cpp
|
llama.cpp/examples/common.cpp
|
||||||
llmodel.h llmodel_c.h
|
llmodel.h llmodel_c.h llmodel_c.cpp
|
||||||
utils.h utils.cpp
|
utils.h utils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
154
network.cpp
154
network.cpp
@ -21,15 +21,22 @@ Network *Network::globalInstance()
|
|||||||
Network::Network()
|
Network::Network()
|
||||||
: QObject{nullptr}
|
: QObject{nullptr}
|
||||||
, m_isActive(false)
|
, m_isActive(false)
|
||||||
|
, m_isOptIn(false)
|
||||||
|
, m_shouldSendStartup(false)
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.sync();
|
settings.sync();
|
||||||
|
m_isOptIn = settings.value("track", false).toBool();
|
||||||
m_uniqueId = settings.value("uniqueId", generateUniqueId()).toString();
|
m_uniqueId = settings.value("uniqueId", generateUniqueId()).toString();
|
||||||
settings.setValue("uniqueId", m_uniqueId);
|
settings.setValue("uniqueId", m_uniqueId);
|
||||||
settings.sync();
|
settings.sync();
|
||||||
setActive(settings.value("network/isActive", false).toBool());
|
setActive(settings.value("network/isActive", false).toBool());
|
||||||
|
if (m_isOptIn)
|
||||||
|
sendIpify();
|
||||||
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this,
|
connect(&m_networkManager, &QNetworkAccessManager::sslErrors, this,
|
||||||
&Network::handleSslErrors);
|
&Network::handleSslErrors);
|
||||||
|
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this,
|
||||||
|
&Network::sendShutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::setActive(bool b)
|
void Network::setActive(bool b)
|
||||||
@ -77,9 +84,10 @@ bool Network::packageAndSendJson(const QString &ingestId, const QString &json)
|
|||||||
newDoc.setObject(object);
|
newDoc.setObject(object);
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
printf("%s", qPrintable(newDoc.toJson(QJsonDocument::Indented)));
|
printf("%s\n", qPrintable(newDoc.toJson(QJsonDocument::Indented)));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QUrl jsonUrl("https://api.gpt4all.io/v1/ingest/chat");
|
QUrl jsonUrl("https://api.gpt4all.io/v1/ingest/chat");
|
||||||
QNetworkRequest request(jsonUrl);
|
QNetworkRequest request(jsonUrl);
|
||||||
QSslConfiguration conf = request.sslConfiguration();
|
QSslConfiguration conf = request.sslConfiguration();
|
||||||
@ -121,7 +129,7 @@ void Network::handleJsonUploadFinished()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
printf("%s", qPrintable(document.toJson(QJsonDocument::Indented)));
|
printf("%s\n", qPrintable(document.toJson(QJsonDocument::Indented)));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -135,6 +143,148 @@ void Network::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &erro
|
|||||||
qWarning() << "ERROR: Received ssl error:" << e.errorString() << "for" << url;
|
qWarning() << "ERROR: Received ssl error:" << e.errorString() << "for" << url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Network::sendModelLoaded()
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
sendMixpanelEvent("model_load");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendResetContext()
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
sendMixpanelEvent("reset_context");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendStartup()
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
m_shouldSendStartup = true;
|
||||||
|
if (m_ipify.isEmpty())
|
||||||
|
return; // when it completes it will send
|
||||||
|
sendMixpanelEvent("startup");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendShutdown()
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
sendMixpanelEvent("shutdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendMixpanelEvent(const QString &ev)
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QJsonObject properties;
|
||||||
|
properties.insert("token", "ce362e568ddaee16ed243eaffb5860a2");
|
||||||
|
properties.insert("time", QDateTime::currentSecsSinceEpoch());
|
||||||
|
properties.insert("distinct_id", m_uniqueId);
|
||||||
|
properties.insert("$insert_id", generateUniqueId());
|
||||||
|
properties.insert("$os", QSysInfo::prettyProductName());
|
||||||
|
if (!m_ipify.isEmpty())
|
||||||
|
properties.insert("ip", m_ipify);
|
||||||
|
properties.insert("name", QCoreApplication::applicationName() + " v"
|
||||||
|
+ QCoreApplication::applicationVersion());
|
||||||
|
properties.insert("model", LLM::globalInstance()->modelName());
|
||||||
|
|
||||||
|
QJsonObject event;
|
||||||
|
event.insert("event", ev);
|
||||||
|
event.insert("properties", properties);
|
||||||
|
|
||||||
|
QJsonArray array;
|
||||||
|
array.append(event);
|
||||||
|
|
||||||
|
QJsonDocument doc;
|
||||||
|
doc.setArray(array);
|
||||||
|
sendMixpanel(doc.toJson());
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
printf("%s %s\n", qPrintable(ev), qPrintable(doc.toJson(QJsonDocument::Indented)));
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendIpify()
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUrl ipifyUrl("https://api.ipify.org");
|
||||||
|
QNetworkRequest request(ipifyUrl);
|
||||||
|
QSslConfiguration conf = request.sslConfiguration();
|
||||||
|
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
request.setSslConfiguration(conf);
|
||||||
|
QNetworkReply *reply = m_networkManager.get(request);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &Network::handleIpifyFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::sendMixpanel(const QByteArray &json)
|
||||||
|
{
|
||||||
|
if (!m_isOptIn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUrl trackUrl("https://api.mixpanel.com/track");
|
||||||
|
QNetworkRequest request(trackUrl);
|
||||||
|
QSslConfiguration conf = request.sslConfiguration();
|
||||||
|
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
|
request.setSslConfiguration(conf);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
QNetworkReply *trackReply = m_networkManager.post(request, json);
|
||||||
|
connect(trackReply, &QNetworkReply::finished, this, &Network::handleMixpanelFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::handleIpifyFinished()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_isOptIn);
|
||||||
|
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||||
|
if (!reply)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QVariant response = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
|
Q_ASSERT(response.isValid());
|
||||||
|
bool ok;
|
||||||
|
int code = response.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
qWarning() << "ERROR: ipify invalid response.";
|
||||||
|
if (code != 200)
|
||||||
|
qWarning() << "ERROR: ipify response != 200 code:" << code;
|
||||||
|
m_ipify = qPrintable(reply->readAll());
|
||||||
|
#if defined(DEBUG)
|
||||||
|
printf("ipify finished %s\n", m_ipify.toLatin1().constData());
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (m_shouldSendStartup)
|
||||||
|
sendStartup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Network::handleMixpanelFinished()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_isOptIn);
|
||||||
|
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||||
|
if (!reply)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QVariant response = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
|
Q_ASSERT(response.isValid());
|
||||||
|
bool ok;
|
||||||
|
int code = response.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
qWarning() << "ERROR: track invalid response.";
|
||||||
|
if (code != 200)
|
||||||
|
qWarning() << "ERROR: track response != 200 code:" << code;
|
||||||
|
#if defined(DEBUG)
|
||||||
|
printf("mixpanel finished %s\n", qPrintable(reply->readAll()));
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
bool Network::sendConversation(const QString &ingestId, const QString &conversation)
|
bool Network::sendConversation(const QString &ingestId, const QString &conversation)
|
||||||
{
|
{
|
||||||
return packageAndSendJson(ingestId, conversation);
|
return packageAndSendJson(ingestId, conversation);
|
||||||
|
14
network.h
14
network.h
@ -22,17 +22,31 @@ Q_SIGNALS:
|
|||||||
void activeChanged();
|
void activeChanged();
|
||||||
void healthCheckFailed(int code);
|
void healthCheckFailed(int code);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void sendModelLoaded();
|
||||||
|
void sendResetContext();
|
||||||
|
void sendStartup();
|
||||||
|
void sendShutdown();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
void handleIpifyFinished();
|
||||||
void handleHealthFinished();
|
void handleHealthFinished();
|
||||||
void handleJsonUploadFinished();
|
void handleJsonUploadFinished();
|
||||||
void handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
|
void handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
|
||||||
|
void handleMixpanelFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendHealth();
|
void sendHealth();
|
||||||
|
void sendIpify();
|
||||||
|
void sendMixpanelEvent(const QString &event);
|
||||||
|
void sendMixpanel(const QByteArray &json);
|
||||||
bool packageAndSendJson(const QString &ingestId, const QString &json);
|
bool packageAndSendJson(const QString &ingestId, const QString &json);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_isOptIn;
|
||||||
|
bool m_shouldSendStartup;
|
||||||
bool m_isActive;
|
bool m_isActive;
|
||||||
|
QString m_ipify;
|
||||||
QString m_uniqueId;
|
QString m_uniqueId;
|
||||||
QNetworkAccessManager m_networkManager;
|
QNetworkAccessManager m_networkManager;
|
||||||
QVector<QNetworkReply*> m_activeUploads;
|
QVector<QNetworkReply*> m_activeUploads;
|
||||||
|
Loading…
Reference in New Issue
Block a user