mirror of
https://github.com/nomic-ai/gpt4all
synced 2024-11-08 07:10:32 +00:00
88a206ab93
Also change SuggestionMode to work the same way. Signed-off-by: Adam Treat <treat.adam@gmail.com> Signed-off-by: Jared Van Bortel <jared@nomic.ai> Co-authored-by: Jared Van Bortel <jared@nomic.ai>
674 lines
28 KiB
C++
674 lines
28 KiB
C++
#include "mysettings.h"
|
|
|
|
#include "../gpt4all-backend/llmodel.h"
|
|
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QGlobalStatic>
|
|
#include <QGuiApplication>
|
|
#include <QIODevice>
|
|
#include <QMap>
|
|
#include <QMetaObject>
|
|
#include <QStandardPaths>
|
|
#include <QThread>
|
|
#include <QUrl>
|
|
#include <QVariant>
|
|
#include <QtLogging>
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
using namespace Qt::Literals::StringLiterals;
|
|
|
|
// used only for settings serialization, do not translate
|
|
static const QStringList suggestionModeNames { "LocalDocsOnly", "On", "Off" };
|
|
static const QStringList chatThemeNames { "Light", "Dark", "LegacyDark" };
|
|
static const QStringList fontSizeNames { "Small", "Medium", "Large" };
|
|
|
|
// FIXME: All of these default strings that are shown in the UI for settings need to be marked as
|
|
// translatable
|
|
|
|
namespace defaults {
|
|
|
|
static const int threadCount = std::min(4, (int32_t) std::thread::hardware_concurrency());
|
|
static const bool forceMetal = false;
|
|
static const bool networkIsActive = false;
|
|
static const bool networkUsageStatsActive = false;
|
|
static const QString device = "Auto";
|
|
static const QString languageAndLocale = "Default";
|
|
|
|
} // namespace defaults
|
|
|
|
static const QVariantMap basicDefaults {
|
|
{ "chatTheme", QVariant::fromValue(ChatTheme::Light) },
|
|
{ "fontSize", QVariant::fromValue(FontSize::Small) },
|
|
{ "lastVersionStarted", "" },
|
|
{ "networkPort", 4891, },
|
|
{ "saveChatsContext", false },
|
|
{ "serverChat", false },
|
|
{ "userDefaultModel", "Application default" },
|
|
{ "suggestionMode", QVariant::fromValue(SuggestionMode::LocalDocsOnly) },
|
|
{ "localdocs/chunkSize", 512 },
|
|
{ "localdocs/retrievalSize", 3 },
|
|
{ "localdocs/showReferences", true },
|
|
{ "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } },
|
|
{ "localdocs/useRemoteEmbed", false },
|
|
{ "localdocs/nomicAPIKey", "" },
|
|
{ "localdocs/embedDevice", "Auto" },
|
|
{ "network/attribution", "" },
|
|
};
|
|
|
|
static QString defaultLocalModelsPath()
|
|
{
|
|
QString localPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
|
|
+ "/";
|
|
QString testWritePath = localPath + u"test_write.txt"_s;
|
|
QString canonicalLocalPath = QFileInfo(localPath).canonicalFilePath() + "/";
|
|
QDir localDir(localPath);
|
|
if (!localDir.exists()) {
|
|
if (!localDir.mkpath(localPath)) {
|
|
qWarning() << "ERROR: Local download directory can't be created:" << canonicalLocalPath;
|
|
return canonicalLocalPath;
|
|
}
|
|
}
|
|
|
|
if (QFileInfo::exists(testWritePath))
|
|
return canonicalLocalPath;
|
|
|
|
QFile testWriteFile(testWritePath);
|
|
if (testWriteFile.open(QIODeviceBase::ReadWrite)) {
|
|
testWriteFile.close();
|
|
return canonicalLocalPath;
|
|
}
|
|
|
|
qWarning() << "ERROR: Local download path appears not writeable:" << canonicalLocalPath;
|
|
return canonicalLocalPath;
|
|
}
|
|
|
|
static QStringList getDevices(bool skipKompute = false)
|
|
{
|
|
QStringList deviceList { "Auto" };
|
|
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
|
deviceList << "Metal";
|
|
#else
|
|
std::vector<LLModel::GPUDevice> devices = LLModel::Implementation::availableGPUDevices();
|
|
for (LLModel::GPUDevice &d : devices) {
|
|
if (!skipKompute || strcmp(d.backend, "kompute"))
|
|
deviceList << QString::fromStdString(d.selectionName());
|
|
}
|
|
#endif
|
|
deviceList << "CPU";
|
|
return deviceList;
|
|
}
|
|
|
|
static QString getUiLanguage(const QString directory, const QString fileName)
|
|
{
|
|
QTranslator translator;
|
|
const QString filePath = directory + QDir::separator() + fileName;
|
|
if (translator.load(filePath)) {
|
|
const QString lang = fileName.mid(fileName.indexOf('_') + 1,
|
|
fileName.lastIndexOf('.') - fileName.indexOf('_') - 1);
|
|
return lang;
|
|
}
|
|
|
|
qDebug() << "ERROR: Failed to load translation file:" << filePath;
|
|
return QString();
|
|
}
|
|
|
|
static QStringList getUiLanguages(const QString &modelPath)
|
|
{
|
|
QStringList languageList( { QObject::tr("Default") } );
|
|
|
|
// Add the language translations from model path files first which is used by translation developers
|
|
// to load translations in progress without having to rebuild all of GPT4All from source
|
|
{
|
|
const QDir dir(modelPath);
|
|
const QStringList qmFiles = dir.entryList({"*.qm"}, QDir::Files);
|
|
for (const QString &fileName : qmFiles)
|
|
languageList << getUiLanguage(modelPath, fileName);
|
|
}
|
|
|
|
// Now add the internal language translations
|
|
{
|
|
const QDir dir(":/i18n");
|
|
const QStringList qmFiles = dir.entryList({"*.qm"}, QDir::Files);
|
|
for (const QString &fileName : qmFiles) {
|
|
const QString lang = getUiLanguage(":/i18n", fileName);
|
|
if (!languageList.contains(lang))
|
|
languageList.append(lang);
|
|
}
|
|
}
|
|
return languageList;
|
|
}
|
|
|
|
class MyPrivateSettings: public MySettings { };
|
|
Q_GLOBAL_STATIC(MyPrivateSettings, settingsInstance)
|
|
MySettings *MySettings::globalInstance()
|
|
{
|
|
return settingsInstance();
|
|
}
|
|
|
|
MySettings::MySettings()
|
|
: QObject(nullptr)
|
|
, m_deviceList(getDevices())
|
|
, m_embeddingsDeviceList(getDevices(/*skipKompute*/ true))
|
|
, m_uiLanguages(getUiLanguages(modelPath()))
|
|
{
|
|
}
|
|
|
|
QVariant MySettings::getBasicSetting(const QString &name) const
|
|
{
|
|
return m_settings.value(name, basicDefaults.value(name));
|
|
}
|
|
|
|
void MySettings::setBasicSetting(const QString &name, const QVariant &value, std::optional<QString> signal)
|
|
{
|
|
if (getBasicSetting(name) == value)
|
|
return;
|
|
|
|
m_settings.setValue(name, value);
|
|
QMetaObject::invokeMethod(this, u"%1Changed"_s.arg(signal.value_or(name)).toLatin1().constData());
|
|
}
|
|
|
|
int MySettings::getEnumSetting(const QString &setting, const QStringList &valueNames) const
|
|
{
|
|
int idx = valueNames.indexOf(getBasicSetting(setting).toString());
|
|
return idx != -1 ? idx : *reinterpret_cast<const int *>(basicDefaults.value(setting).constData());
|
|
}
|
|
|
|
void MySettings::restoreModelDefaults(const ModelInfo &info)
|
|
{
|
|
setModelTemperature(info, info.m_temperature);
|
|
setModelTopP(info, info.m_topP);
|
|
setModelMinP(info, info.m_minP);
|
|
setModelTopK(info, info.m_topK);;
|
|
setModelMaxLength(info, info.m_maxLength);
|
|
setModelPromptBatchSize(info, info.m_promptBatchSize);
|
|
setModelContextLength(info, info.m_contextLength);
|
|
setModelGpuLayers(info, info.m_gpuLayers);
|
|
setModelRepeatPenalty(info, info.m_repeatPenalty);
|
|
setModelRepeatPenaltyTokens(info, info.m_repeatPenaltyTokens);
|
|
setModelPromptTemplate(info, info.m_promptTemplate);
|
|
setModelSystemPrompt(info, info.m_systemPrompt);
|
|
setModelChatNamePrompt(info, info.m_chatNamePrompt);
|
|
setModelSuggestedFollowUpPrompt(info, info.m_suggestedFollowUpPrompt);
|
|
}
|
|
|
|
void MySettings::restoreApplicationDefaults()
|
|
{
|
|
setChatTheme(basicDefaults.value("chatTheme").value<ChatTheme>());
|
|
setFontSize(basicDefaults.value("fontSize").value<FontSize>());
|
|
setDevice(defaults::device);
|
|
setThreadCount(defaults::threadCount);
|
|
setSaveChatsContext(basicDefaults.value("saveChatsContext").toBool());
|
|
setServerChat(basicDefaults.value("serverChat").toBool());
|
|
setNetworkPort(basicDefaults.value("networkPort").toInt());
|
|
setModelPath(defaultLocalModelsPath());
|
|
setUserDefaultModel(basicDefaults.value("userDefaultModel").toString());
|
|
setForceMetal(defaults::forceMetal);
|
|
setSuggestionMode(basicDefaults.value("suggestionMode").value<SuggestionMode>());
|
|
setLanguageAndLocale(defaults::languageAndLocale);
|
|
}
|
|
|
|
void MySettings::restoreLocalDocsDefaults()
|
|
{
|
|
setLocalDocsChunkSize(basicDefaults.value("localdocs/chunkSize").toInt());
|
|
setLocalDocsRetrievalSize(basicDefaults.value("localdocs/retrievalSize").toInt());
|
|
setLocalDocsShowReferences(basicDefaults.value("localdocs/showReferences").toBool());
|
|
setLocalDocsFileExtensions(basicDefaults.value("localdocs/fileExtensions").toStringList());
|
|
setLocalDocsUseRemoteEmbed(basicDefaults.value("localdocs/useRemoteEmbed").toBool());
|
|
setLocalDocsNomicAPIKey(basicDefaults.value("localdocs/nomicAPIKey").toString());
|
|
setLocalDocsEmbedDevice(basicDefaults.value("localdocs/embedDevice").toString());
|
|
}
|
|
|
|
void MySettings::eraseModel(const ModelInfo &info)
|
|
{
|
|
m_settings.remove(u"model-%1"_s.arg(info.id()));
|
|
}
|
|
|
|
QString MySettings::modelName(const ModelInfo &info) const
|
|
{
|
|
return m_settings.value(u"model-%1/name"_s.arg(info.id()),
|
|
!info.m_name.isEmpty() ? info.m_name : info.m_filename).toString();
|
|
}
|
|
|
|
void MySettings::setModelName(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
if ((modelName(info) == value || info.id().isEmpty()) && !force)
|
|
return;
|
|
|
|
if ((info.m_name == value || info.m_filename == value) && !info.shouldSaveMetadata())
|
|
m_settings.remove(u"model-%1/name"_s.arg(info.id()));
|
|
else
|
|
m_settings.setValue(u"model-%1/name"_s.arg(info.id()), value);
|
|
if (!force)
|
|
emit nameChanged(info);
|
|
}
|
|
|
|
static QString modelSettingName(const ModelInfo &info, const QString &name)
|
|
{
|
|
return u"model-%1/%2"_s.arg(info.id(), name);
|
|
}
|
|
|
|
QVariant MySettings::getModelSetting(const QString &name, const ModelInfo &info) const
|
|
{
|
|
return m_settings.value(modelSettingName(info, name), info.getFields().value(name));
|
|
}
|
|
|
|
void MySettings::setModelSetting(const QString &name, const ModelInfo &info, const QVariant &value, bool force,
|
|
bool signal)
|
|
{
|
|
if (!force && (info.id().isEmpty() || getModelSetting(name, info) == value))
|
|
return;
|
|
|
|
QString settingName = modelSettingName(info, name);
|
|
if (info.getFields().value(name) == value && !info.shouldSaveMetadata())
|
|
m_settings.remove(settingName);
|
|
else
|
|
m_settings.setValue(settingName, value);
|
|
if (signal && !force)
|
|
QMetaObject::invokeMethod(this, u"%1Changed"_s.arg(name).toLatin1().constData(), Q_ARG(ModelInfo, info));
|
|
}
|
|
|
|
QString MySettings::modelFilename (const ModelInfo &info) const { return getModelSetting("filename", info).toString(); }
|
|
QString MySettings::modelDescription (const ModelInfo &info) const { return getModelSetting("description", info).toString(); }
|
|
QString MySettings::modelUrl (const ModelInfo &info) const { return getModelSetting("url", info).toString(); }
|
|
QString MySettings::modelQuant (const ModelInfo &info) const { return getModelSetting("quant", info).toString(); }
|
|
QString MySettings::modelType (const ModelInfo &info) const { return getModelSetting("type", info).toString(); }
|
|
bool MySettings::modelIsClone (const ModelInfo &info) const { return getModelSetting("isClone", info).toBool(); }
|
|
bool MySettings::modelIsDiscovered (const ModelInfo &info) const { return getModelSetting("isDiscovered", info).toBool(); }
|
|
int MySettings::modelLikes (const ModelInfo &info) const { return getModelSetting("likes", info).toInt(); }
|
|
int MySettings::modelDownloads (const ModelInfo &info) const { return getModelSetting("downloads", info).toInt(); }
|
|
QDateTime MySettings::modelRecency (const ModelInfo &info) const { return getModelSetting("recency", info).toDateTime(); }
|
|
double MySettings::modelTemperature (const ModelInfo &info) const { return getModelSetting("temperature", info).toDouble(); }
|
|
double MySettings::modelTopP (const ModelInfo &info) const { return getModelSetting("topP", info).toDouble(); }
|
|
double MySettings::modelMinP (const ModelInfo &info) const { return getModelSetting("minP", info).toDouble(); }
|
|
int MySettings::modelTopK (const ModelInfo &info) const { return getModelSetting("topK", info).toInt(); }
|
|
int MySettings::modelMaxLength (const ModelInfo &info) const { return getModelSetting("maxLength", info).toInt(); }
|
|
int MySettings::modelPromptBatchSize (const ModelInfo &info) const { return getModelSetting("promptBatchSize", info).toInt(); }
|
|
int MySettings::modelContextLength (const ModelInfo &info) const { return getModelSetting("contextLength", info).toInt(); }
|
|
int MySettings::modelGpuLayers (const ModelInfo &info) const { return getModelSetting("gpuLayers", info).toInt(); }
|
|
double MySettings::modelRepeatPenalty (const ModelInfo &info) const { return getModelSetting("repeatPenalty", info).toDouble(); }
|
|
int MySettings::modelRepeatPenaltyTokens (const ModelInfo &info) const { return getModelSetting("repeatPenaltyTokens", info).toInt(); }
|
|
QString MySettings::modelPromptTemplate (const ModelInfo &info) const { return getModelSetting("promptTemplate", info).toString(); }
|
|
QString MySettings::modelSystemPrompt (const ModelInfo &info) const { return getModelSetting("systemPrompt", info).toString(); }
|
|
QString MySettings::modelChatNamePrompt (const ModelInfo &info) const { return getModelSetting("chatNamePrompt", info).toString(); }
|
|
QString MySettings::modelSuggestedFollowUpPrompt(const ModelInfo &info) const { return getModelSetting("suggestedFollowUpPrompt", info).toString(); }
|
|
|
|
void MySettings::setModelFilename(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("filename", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelDescription(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("description", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelUrl(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("url", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelQuant(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("quant", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelType(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("type", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelIsClone(const ModelInfo &info, bool value, bool force)
|
|
{
|
|
setModelSetting("isClone", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelIsDiscovered(const ModelInfo &info, bool value, bool force)
|
|
{
|
|
setModelSetting("isDiscovered", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelLikes(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("likes", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelDownloads(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("downloads", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelRecency(const ModelInfo &info, const QDateTime &value, bool force)
|
|
{
|
|
setModelSetting("recency", info, value, force);
|
|
}
|
|
|
|
void MySettings::setModelTemperature(const ModelInfo &info, double value, bool force)
|
|
{
|
|
setModelSetting("temperature", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelTopP(const ModelInfo &info, double value, bool force)
|
|
{
|
|
setModelSetting("topP", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelMinP(const ModelInfo &info, double value, bool force)
|
|
{
|
|
setModelSetting("minP", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelTopK(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("topK", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelMaxLength(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("maxLength", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelPromptBatchSize(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("promptBatchSize", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelContextLength(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("contextLength", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelGpuLayers(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("gpuLayers", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelRepeatPenalty(const ModelInfo &info, double value, bool force)
|
|
{
|
|
setModelSetting("repeatPenalty", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelRepeatPenaltyTokens(const ModelInfo &info, int value, bool force)
|
|
{
|
|
setModelSetting("repeatPenaltyTokens", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelPromptTemplate(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("promptTemplate", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelSystemPrompt(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("systemPrompt", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelChatNamePrompt(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("chatNamePrompt", info, value, force, true);
|
|
}
|
|
|
|
void MySettings::setModelSuggestedFollowUpPrompt(const ModelInfo &info, const QString &value, bool force)
|
|
{
|
|
setModelSetting("suggestedFollowUpPrompt", info, value, force, true);
|
|
}
|
|
|
|
int MySettings::threadCount() const
|
|
{
|
|
int c = m_settings.value("threadCount", defaults::threadCount).toInt();
|
|
// The old thread setting likely left many people with 0 in settings config file, which means
|
|
// we should reset it to the default going forward
|
|
if (c <= 0)
|
|
c = defaults::threadCount;
|
|
c = std::max(c, 1);
|
|
c = std::min(c, QThread::idealThreadCount());
|
|
return c;
|
|
}
|
|
|
|
void MySettings::setThreadCount(int value)
|
|
{
|
|
if (threadCount() == value)
|
|
return;
|
|
|
|
value = std::max(value, 1);
|
|
value = std::min(value, QThread::idealThreadCount());
|
|
m_settings.setValue("threadCount", value);
|
|
emit threadCountChanged();
|
|
}
|
|
|
|
bool MySettings::saveChatsContext() const { return getBasicSetting("saveChatsContext" ).toBool(); }
|
|
bool MySettings::serverChat() const { return getBasicSetting("serverChat" ).toBool(); }
|
|
int MySettings::networkPort() const { return getBasicSetting("networkPort" ).toInt(); }
|
|
QString MySettings::userDefaultModel() const { return getBasicSetting("userDefaultModel" ).toString(); }
|
|
QString MySettings::lastVersionStarted() const { return getBasicSetting("lastVersionStarted" ).toString(); }
|
|
int MySettings::localDocsChunkSize() const { return getBasicSetting("localdocs/chunkSize" ).toInt(); }
|
|
int MySettings::localDocsRetrievalSize() const { return getBasicSetting("localdocs/retrievalSize" ).toInt(); }
|
|
bool MySettings::localDocsShowReferences() const { return getBasicSetting("localdocs/showReferences").toBool(); }
|
|
QStringList MySettings::localDocsFileExtensions() const { return getBasicSetting("localdocs/fileExtensions").toStringList(); }
|
|
bool MySettings::localDocsUseRemoteEmbed() const { return getBasicSetting("localdocs/useRemoteEmbed").toBool(); }
|
|
QString MySettings::localDocsNomicAPIKey() const { return getBasicSetting("localdocs/nomicAPIKey" ).toString(); }
|
|
QString MySettings::localDocsEmbedDevice() const { return getBasicSetting("localdocs/embedDevice" ).toString(); }
|
|
QString MySettings::networkAttribution() const { return getBasicSetting("network/attribution" ).toString(); }
|
|
|
|
ChatTheme MySettings::chatTheme() const { return ChatTheme (getEnumSetting("chatTheme", chatThemeNames)); }
|
|
FontSize MySettings::fontSize() const { return FontSize (getEnumSetting("fontSize", fontSizeNames)); }
|
|
SuggestionMode MySettings::suggestionMode() const { return SuggestionMode(getEnumSetting("suggestionMode", suggestionModeNames)); }
|
|
|
|
void MySettings::setSaveChatsContext(bool value) { setBasicSetting("saveChatsContext", value); }
|
|
void MySettings::setServerChat(bool value) { setBasicSetting("serverChat", value); }
|
|
void MySettings::setNetworkPort(int value) { setBasicSetting("networkPort", value); }
|
|
void MySettings::setUserDefaultModel(const QString &value) { setBasicSetting("userDefaultModel", value); }
|
|
void MySettings::setLastVersionStarted(const QString &value) { setBasicSetting("lastVersionStarted", value); }
|
|
void MySettings::setLocalDocsChunkSize(int value) { setBasicSetting("localdocs/chunkSize", value, "localDocsChunkSize"); }
|
|
void MySettings::setLocalDocsRetrievalSize(int value) { setBasicSetting("localdocs/retrievalSize", value, "localDocsRetrievalSize"); }
|
|
void MySettings::setLocalDocsShowReferences(bool value) { setBasicSetting("localdocs/showReferences", value, "localDocsShowReferences"); }
|
|
void MySettings::setLocalDocsFileExtensions(const QStringList &value) { setBasicSetting("localdocs/fileExtensions", value, "localDocsFileExtensions"); }
|
|
void MySettings::setLocalDocsUseRemoteEmbed(bool value) { setBasicSetting("localdocs/useRemoteEmbed", value, "localDocsUseRemoteEmbed"); }
|
|
void MySettings::setLocalDocsNomicAPIKey(const QString &value) { setBasicSetting("localdocs/nomicAPIKey", value, "localDocsNomicAPIKey"); }
|
|
void MySettings::setLocalDocsEmbedDevice(const QString &value) { setBasicSetting("localdocs/embedDevice", value, "localDocsEmbedDevice"); }
|
|
void MySettings::setNetworkAttribution(const QString &value) { setBasicSetting("network/attribution", value, "networkAttribution"); }
|
|
|
|
void MySettings::setChatTheme(ChatTheme value) { setBasicSetting("chatTheme", chatThemeNames .value(int(value))); }
|
|
void MySettings::setFontSize(FontSize value) { setBasicSetting("fontSize", fontSizeNames .value(int(value))); }
|
|
void MySettings::setSuggestionMode(SuggestionMode value) { setBasicSetting("suggestionMode", suggestionModeNames.value(int(value))); }
|
|
|
|
QString MySettings::modelPath()
|
|
{
|
|
// We have to migrate the old setting because I changed the setting key recklessly in v2.4.11
|
|
// which broke a lot of existing installs
|
|
const bool containsOldSetting = m_settings.contains("modelPaths");
|
|
if (containsOldSetting) {
|
|
const bool containsNewSetting = m_settings.contains("modelPath");
|
|
if (!containsNewSetting)
|
|
m_settings.setValue("modelPath", m_settings.value("modelPaths"));
|
|
m_settings.remove("modelPaths");
|
|
}
|
|
return m_settings.value("modelPath", defaultLocalModelsPath()).toString();
|
|
}
|
|
|
|
void MySettings::setModelPath(const QString &value)
|
|
{
|
|
QString filePath = (value.startsWith("file://") ?
|
|
QUrl(value).toLocalFile() : value);
|
|
QString canonical = QFileInfo(filePath).canonicalFilePath() + "/";
|
|
if (modelPath() == canonical)
|
|
return;
|
|
m_settings.setValue("modelPath", canonical);
|
|
emit modelPathChanged();
|
|
}
|
|
|
|
QString MySettings::device()
|
|
{
|
|
auto value = m_settings.value("device");
|
|
if (!value.isValid())
|
|
return defaults::device;
|
|
|
|
auto device = value.toString();
|
|
if (!device.isEmpty()) {
|
|
auto deviceStr = device.toStdString();
|
|
auto newNameStr = LLModel::GPUDevice::updateSelectionName(deviceStr);
|
|
if (newNameStr != deviceStr) {
|
|
auto newName = QString::fromStdString(newNameStr);
|
|
qWarning() << "updating device name:" << device << "->" << newName;
|
|
device = newName;
|
|
m_settings.setValue("device", device);
|
|
}
|
|
}
|
|
return device;
|
|
}
|
|
|
|
void MySettings::setDevice(const QString &value)
|
|
{
|
|
if (device() != value) {
|
|
m_settings.setValue("device", value);
|
|
emit deviceChanged();
|
|
}
|
|
}
|
|
|
|
bool MySettings::forceMetal() const
|
|
{
|
|
return m_forceMetal;
|
|
}
|
|
|
|
void MySettings::setForceMetal(bool value)
|
|
{
|
|
if (m_forceMetal != value) {
|
|
m_forceMetal = value;
|
|
emit forceMetalChanged(value);
|
|
}
|
|
}
|
|
|
|
bool MySettings::networkIsActive() const
|
|
{
|
|
return m_settings.value("network/isActive", defaults::networkIsActive).toBool();
|
|
}
|
|
|
|
bool MySettings::isNetworkIsActiveSet() const
|
|
{
|
|
return m_settings.value("network/isActive").isValid();
|
|
}
|
|
|
|
void MySettings::setNetworkIsActive(bool value)
|
|
{
|
|
auto cur = m_settings.value("network/isActive");
|
|
if (!cur.isValid() || cur.toBool() != value) {
|
|
m_settings.setValue("network/isActive", value);
|
|
emit networkIsActiveChanged();
|
|
}
|
|
}
|
|
|
|
bool MySettings::networkUsageStatsActive() const
|
|
{
|
|
return m_settings.value("network/usageStatsActive", defaults::networkUsageStatsActive).toBool();
|
|
}
|
|
|
|
bool MySettings::isNetworkUsageStatsActiveSet() const
|
|
{
|
|
return m_settings.value("network/usageStatsActive").isValid();
|
|
}
|
|
|
|
void MySettings::setNetworkUsageStatsActive(bool value)
|
|
{
|
|
auto cur = m_settings.value("network/usageStatsActive");
|
|
if (!cur.isValid() || cur.toBool() != value) {
|
|
m_settings.setValue("network/usageStatsActive", value);
|
|
emit networkUsageStatsActiveChanged();
|
|
}
|
|
}
|
|
|
|
QString MySettings::languageAndLocale() const
|
|
{
|
|
auto value = m_settings.value("languageAndLocale");
|
|
if (!value.isValid())
|
|
return defaults::languageAndLocale;
|
|
return value.toString();
|
|
}
|
|
|
|
QString MySettings::filePathForLocale(const QLocale &locale)
|
|
{
|
|
// Check and see if we have a translation for the chosen locale and set it if possible otherwise
|
|
// we return the filepath for the 'en' translation
|
|
QStringList uiLanguages = locale.uiLanguages();
|
|
for (int i = 0; i < uiLanguages.size(); ++i)
|
|
uiLanguages[i].replace('-', '_');
|
|
|
|
// Scan this directory for files named like gpt4all_%1.qm that match and if so return them first
|
|
// this is the model download directory and it can be used by translation developers who are
|
|
// trying to test their translations by just compiling the translation with the lrelease tool
|
|
// rather than having to recompile all of GPT4All
|
|
QString directory = modelPath();
|
|
for (const QString &bcp47Name : uiLanguages) {
|
|
QString filePath = QString("%1/gpt4all_%2.qm").arg(directory).arg(bcp47Name);
|
|
QFileInfo filePathInfo(filePath);
|
|
if (filePathInfo.exists()) return filePath;
|
|
}
|
|
|
|
// Now scan the internal built-in translations
|
|
for (QString bcp47Name : uiLanguages) {
|
|
QString filePath = QString(":/i18n/gpt4all_%1.qm").arg(bcp47Name);
|
|
QFileInfo filePathInfo(filePath);
|
|
if (filePathInfo.exists()) return filePath;
|
|
}
|
|
return QString(":/i18n/gpt4all_en.qm");
|
|
}
|
|
|
|
void MySettings::setLanguageAndLocale(const QString &bcp47Name)
|
|
{
|
|
if (!bcp47Name.isEmpty() && languageAndLocale() != bcp47Name)
|
|
m_settings.setValue("languageAndLocale", bcp47Name);
|
|
|
|
// When the app is started this method is called with no bcp47Name given which sets the translation
|
|
// to either the default which is the system locale or the one explicitly set by the user previously.
|
|
QLocale locale;
|
|
const QString l = languageAndLocale();
|
|
if (l == "Default")
|
|
locale = QLocale::system();
|
|
else
|
|
locale = QLocale(l);
|
|
|
|
// If we previously installed a translator, then remove it
|
|
if (m_translator) {
|
|
if (!qGuiApp->removeTranslator(m_translator)) {
|
|
qDebug() << "ERROR: Failed to remove the previous translator";
|
|
} else {
|
|
delete m_translator;
|
|
m_translator = nullptr;
|
|
}
|
|
}
|
|
|
|
// We expect that the translator was removed and is now a nullptr
|
|
Q_ASSERT(!m_translator);
|
|
|
|
const QString filePath = filePathForLocale(locale);
|
|
// Installing the default gpt4all_en.qm fails presumably because it has no strings that are
|
|
// different from the ones stored in the binary
|
|
if (!m_translator && !filePath.endsWith("en.qm")) {
|
|
// Create a new translator object on the heap
|
|
m_translator = new QTranslator(this);
|
|
bool success = m_translator->load(filePath);
|
|
Q_ASSERT(success);
|
|
if (!success) {
|
|
qDebug() << "ERROR: Failed to load translation file:" << filePath;
|
|
delete m_translator;
|
|
m_translator = nullptr;
|
|
}
|
|
|
|
// If we've successfully loaded it, then try and install it
|
|
if (!qGuiApp->installTranslator(m_translator)) {
|
|
qDebug() << "ERROR: Failed to install the translator:" << filePath;
|
|
delete m_translator;
|
|
m_translator = nullptr;
|
|
}
|
|
}
|
|
|
|
// Finally, set the locale whether we have a translation or not
|
|
QLocale::setDefault(locale);
|
|
emit languageAndLocaleChanged();
|
|
}
|