UI and embedding device changes for GPT4All v3.0.0-rc3 (#2477)

Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
Jared Van Bortel 2024-06-28 12:57:57 -04:00 committed by GitHub
parent 426aa5eb47
commit 2c8d634b5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 661 additions and 562 deletions

View File

@ -132,39 +132,40 @@ qt_add_qml_module(chat
main.qml
qml/AddCollectionView.qml
qml/AddModelView.qml
qml/ApplicationSettings.qml
qml/ChatDrawer.qml
qml/ChatView.qml
qml/CollectionsDrawer.qml
qml/HomeView.qml
qml/LocalDocsSettings.qml
qml/LocalDocsView.qml
qml/ModelSettings.qml
qml/ModelsView.qml
qml/NetworkDialog.qml
qml/NewVersionDialog.qml
qml/ThumbsDownDialog.qml
qml/PopupDialog.qml
qml/SettingsView.qml
qml/StartupDialog.qml
qml/PopupDialog.qml
qml/Theme.qml
qml/ModelSettings.qml
qml/ApplicationSettings.qml
qml/LocalDocsSettings.qml
qml/LocalDocsView.qml
qml/SwitchModelDialog.qml
qml/MySettingsTab.qml
qml/MySettingsStack.qml
qml/MySettingsDestructiveButton.qml
qml/MySettingsButton.qml
qml/MySettingsLabel.qml
qml/MySlug.qml
qml/Theme.qml
qml/ThumbsDownDialog.qml
qml/MyBusyIndicator.qml
qml/MyButton.qml
qml/MyCheckBox.qml
qml/MyComboBox.qml
qml/MyDialog.qml
qml/MyDirectoryField.qml
qml/MyFancyLink.qml
qml/MyTextArea.qml
qml/MyTextField.qml
qml/MyCheckBox.qml
qml/MyBusyIndicator.qml
qml/MyMiniButton.qml
qml/MySettingsButton.qml
qml/MySettingsDestructiveButton.qml
qml/MySettingsLabel.qml
qml/MySettingsStack.qml
qml/MySettingsTab.qml
qml/MySlug.qml
qml/MyTextArea.qml
qml/MyTextButton.qml
qml/MyTextField.qml
qml/MyToolButton.qml
qml/MyWelcomeButton.qml
RESOURCES

View File

@ -17,7 +17,6 @@
#include <QMutexLocker>
#include <QSet>
#include <QStringList>
#include <QVariantMap>
#include <QWaitCondition>
#include <Qt>
#include <QtLogging>
@ -340,181 +339,8 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
model->setRequestURL(modelInfo.url());
model->setAPIKey(apiKey);
m_llModelInfo.resetModel(this, model);
} else {
QElapsedTimer modelLoadTimer;
modelLoadTimer.start();
auto requestedDevice = MySettings::globalInstance()->device();
auto n_ctx = MySettings::globalInstance()->modelContextLength(modelInfo);
m_ctx.n_ctx = n_ctx;
auto ngl = MySettings::globalInstance()->modelGpuLayers(modelInfo);
std::string backend = "auto";
#ifdef Q_OS_MAC
if (requestedDevice == "CPU") {
backend = "cpu";
} else if (m_forceMetal) {
#ifdef __aarch64__
backend = "metal";
#endif
}
#else // !defined(Q_OS_MAC)
if (requestedDevice.startsWith("CUDA: "))
backend = "cuda";
#endif
QString constructError;
m_llModelInfo.resetModel(this);
try {
auto *model = LLModel::Implementation::construct(filePath.toStdString(), backend, n_ctx);
m_llModelInfo.resetModel(this, model);
} catch (const LLModel::MissingImplementationError &e) {
modelLoadProps.insert("error", "missing_model_impl");
constructError = e.what();
} catch (const LLModel::UnsupportedModelError &e) {
modelLoadProps.insert("error", "unsupported_model_file");
constructError = e.what();
} catch (const LLModel::BadArchError &e) {
constructError = e.what();
modelLoadProps.insert("error", "unsupported_model_arch");
modelLoadProps.insert("model_arch", QString::fromStdString(e.arch()));
}
if (m_llModelInfo.model) {
if (m_llModelInfo.model->isModelBlacklisted(filePath.toStdString())) {
static QSet<QString> warned;
auto fname = modelInfo.filename();
if (!warned.contains(fname)) {
emit modelLoadingWarning(
u"%1 is known to be broken. Please get a replacement via the download dialog."_s.arg(fname)
);
warned.insert(fname); // don't warn again until restart
}
}
m_llModelInfo.model->setProgressCallback([this](float progress) -> bool {
progress = std::max(progress, std::numeric_limits<float>::min()); // keep progress above zero
emit modelLoadingPercentageChanged(progress);
return m_shouldBeLoaded;
});
auto approxDeviceMemGB = [](const LLModel::GPUDevice *dev) {
float memGB = dev->heapSize / float(1024 * 1024 * 1024);
return std::floor(memGB * 10.f) / 10.f; // truncate to 1 decimal place
};
std::vector<LLModel::GPUDevice> availableDevices;
const LLModel::GPUDevice *defaultDevice = nullptr;
{
const size_t requiredMemory = m_llModelInfo.model->requiredMem(filePath.toStdString(), n_ctx, ngl);
availableDevices = m_llModelInfo.model->availableGPUDevices(requiredMemory);
// Pick the best device
// NB: relies on the fact that Kompute devices are listed first
if (!availableDevices.empty() && availableDevices.front().type == 2 /*a discrete gpu*/) {
defaultDevice = &availableDevices.front();
float memGB = defaultDevice->heapSize / float(1024 * 1024 * 1024);
memGB = std::floor(memGB * 10.f) / 10.f; // truncate to 1 decimal place
modelLoadProps.insert("default_device", QString::fromStdString(defaultDevice->name));
modelLoadProps.insert("default_device_mem", approxDeviceMemGB(defaultDevice));
modelLoadProps.insert("default_device_backend", QString::fromStdString(defaultDevice->backendName()));
}
}
bool actualDeviceIsCPU = true;
#if defined(Q_OS_MAC) && defined(__aarch64__)
if (m_llModelInfo.model->implementation().buildVariant() == "metal")
actualDeviceIsCPU = false;
#else
if (requestedDevice != "CPU") {
const auto *device = defaultDevice;
if (requestedDevice != "Auto") {
// Use the selected device
for (const LLModel::GPUDevice &d : availableDevices) {
if (QString::fromStdString(d.selectionName()) == requestedDevice) {
device = &d;
break;
}
}
}
std::string unavail_reason;
if (!device) {
// GPU not available
} else if (!m_llModelInfo.model->initializeGPUDevice(device->index, &unavail_reason)) {
m_llModelInfo.fallbackReason = QString::fromStdString(unavail_reason);
} else {
actualDeviceIsCPU = false;
modelLoadProps.insert("requested_device_mem", approxDeviceMemGB(device));
}
}
#endif
// Report which device we're actually using
bool success = m_llModelInfo.model->loadModel(filePath.toStdString(), n_ctx, ngl);
if (!m_shouldBeLoaded) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingPercentageChanged(0.0f);
return false;
}
if (actualDeviceIsCPU) {
// we asked llama.cpp to use the CPU
} else if (!success) {
// llama_init_from_file returned nullptr
m_llModelInfo.fallbackReason = "GPU loading failed (out of VRAM?)";
modelLoadProps.insert("cpu_fallback_reason", "gpu_load_failed");
success = m_llModelInfo.model->loadModel(filePath.toStdString(), n_ctx, 0);
if (!m_shouldBeLoaded) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingPercentageChanged(0.0f);
return false;
}
} else if (!m_llModelInfo.model->usingGPUDevice()) {
// ggml_vk_init was not called in llama.cpp
// We might have had to fallback to CPU after load if the model is not possible to accelerate
// for instance if the quantization method is not supported on Vulkan yet
m_llModelInfo.fallbackReason = "model or quant has no GPU support";
modelLoadProps.insert("cpu_fallback_reason", "gpu_unsupported_model");
}
if (!success) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Could not load model due to invalid model file for %1"_s.arg(modelInfo.filename()));
modelLoadProps.insert("error", "loadmodel_failed");
} else {
switch (m_llModelInfo.model->implementation().modelType()[0]) {
case 'L': m_llModelType = LLModelType::LLAMA_; break;
case 'G': m_llModelType = LLModelType::GPTJ_; break;
default:
{
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Could not determine model type for %1"_s.arg(modelInfo.filename()));
}
}
modelLoadProps.insert("$duration", modelLoadTimer.elapsed() / 1000.);
}
} else {
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Error loading %1: %2"_s.arg(modelInfo.filename(), constructError));
}
} else if (!loadNewModel(modelInfo, modelLoadProps)) {
return false; // m_shouldBeLoaded became false
}
#if defined(DEBUG_MODEL_LOADING)
qDebug() << "new model" << m_llmThread.objectName() << m_llModelInfo.model.get();
@ -544,6 +370,201 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
return bool(m_llModelInfo.model);
}
/* Returns false if the model should no longer be loaded (!m_shouldBeLoaded).
* Otherwise returns true, even on error. */
bool ChatLLM::loadNewModel(const ModelInfo &modelInfo, QVariantMap &modelLoadProps)
{
QElapsedTimer modelLoadTimer;
modelLoadTimer.start();
QString requestedDevice = MySettings::globalInstance()->device();
int n_ctx = MySettings::globalInstance()->modelContextLength(modelInfo);
m_ctx.n_ctx = n_ctx;
int ngl = MySettings::globalInstance()->modelGpuLayers(modelInfo);
std::string backend = "auto";
#ifdef Q_OS_MAC
if (requestedDevice == "CPU") {
backend = "cpu";
} else if (m_forceMetal) {
#ifdef __aarch64__
backend = "metal";
#endif
}
#else // !defined(Q_OS_MAC)
if (requestedDevice.startsWith("CUDA: "))
backend = "cuda";
#endif
QString filePath = modelInfo.dirpath + modelInfo.filename();
auto construct = [this, &filePath, &modelInfo, &modelLoadProps, n_ctx](std::string const &backend) {
QString constructError;
m_llModelInfo.resetModel(this);
try {
auto *model = LLModel::Implementation::construct(filePath.toStdString(), backend, n_ctx);
m_llModelInfo.resetModel(this, model);
} catch (const LLModel::MissingImplementationError &e) {
modelLoadProps.insert("error", "missing_model_impl");
constructError = e.what();
} catch (const LLModel::UnsupportedModelError &e) {
modelLoadProps.insert("error", "unsupported_model_file");
constructError = e.what();
} catch (const LLModel::BadArchError &e) {
constructError = e.what();
modelLoadProps.insert("error", "unsupported_model_arch");
modelLoadProps.insert("model_arch", QString::fromStdString(e.arch()));
}
if (!m_llModelInfo.model) {
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Error loading %1: %2"_s.arg(modelInfo.filename(), constructError));
return false;
}
m_llModelInfo.model->setProgressCallback([this](float progress) -> bool {
progress = std::max(progress, std::numeric_limits<float>::min()); // keep progress above zero
emit modelLoadingPercentageChanged(progress);
return m_shouldBeLoaded;
});
return true;
};
if (!construct(backend))
return true;
if (m_llModelInfo.model->isModelBlacklisted(filePath.toStdString())) {
static QSet<QString> warned;
auto fname = modelInfo.filename();
if (!warned.contains(fname)) {
emit modelLoadingWarning(
u"%1 is known to be broken. Please get a replacement via the download dialog."_s.arg(fname)
);
warned.insert(fname); // don't warn again until restart
}
}
auto approxDeviceMemGB = [](const LLModel::GPUDevice *dev) {
float memGB = dev->heapSize / float(1024 * 1024 * 1024);
return std::floor(memGB * 10.f) / 10.f; // truncate to 1 decimal place
};
std::vector<LLModel::GPUDevice> availableDevices;
const LLModel::GPUDevice *defaultDevice = nullptr;
{
const size_t requiredMemory = m_llModelInfo.model->requiredMem(filePath.toStdString(), n_ctx, ngl);
availableDevices = m_llModelInfo.model->availableGPUDevices(requiredMemory);
// Pick the best device
// NB: relies on the fact that Kompute devices are listed first
if (!availableDevices.empty() && availableDevices.front().type == 2 /*a discrete gpu*/) {
defaultDevice = &availableDevices.front();
float memGB = defaultDevice->heapSize / float(1024 * 1024 * 1024);
memGB = std::floor(memGB * 10.f) / 10.f; // truncate to 1 decimal place
modelLoadProps.insert("default_device", QString::fromStdString(defaultDevice->name));
modelLoadProps.insert("default_device_mem", approxDeviceMemGB(defaultDevice));
modelLoadProps.insert("default_device_backend", QString::fromStdString(defaultDevice->backendName()));
}
}
bool actualDeviceIsCPU = true;
#if defined(Q_OS_MAC) && defined(__aarch64__)
if (m_llModelInfo.model->implementation().buildVariant() == "metal")
actualDeviceIsCPU = false;
#else
if (requestedDevice != "CPU") {
const auto *device = defaultDevice;
if (requestedDevice != "Auto") {
// Use the selected device
for (const LLModel::GPUDevice &d : availableDevices) {
if (QString::fromStdString(d.selectionName()) == requestedDevice) {
device = &d;
break;
}
}
}
std::string unavail_reason;
if (!device) {
// GPU not available
} else if (!m_llModelInfo.model->initializeGPUDevice(device->index, &unavail_reason)) {
m_llModelInfo.fallbackReason = QString::fromStdString(unavail_reason);
} else {
actualDeviceIsCPU = false;
modelLoadProps.insert("requested_device_mem", approxDeviceMemGB(device));
}
}
#endif
bool success = m_llModelInfo.model->loadModel(filePath.toStdString(), n_ctx, ngl);
if (!m_shouldBeLoaded) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingPercentageChanged(0.0f);
return false;
}
if (actualDeviceIsCPU) {
// we asked llama.cpp to use the CPU
} else if (!success) {
// llama_init_from_file returned nullptr
m_llModelInfo.fallbackReason = "GPU loading failed (out of VRAM?)";
modelLoadProps.insert("cpu_fallback_reason", "gpu_load_failed");
// For CUDA, make sure we don't use the GPU at all - ngl=0 still offloads matmuls
if (backend == "cuda" && !construct("auto"))
return true;
success = m_llModelInfo.model->loadModel(filePath.toStdString(), n_ctx, 0);
if (!m_shouldBeLoaded) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingPercentageChanged(0.0f);
return false;
}
} else if (!m_llModelInfo.model->usingGPUDevice()) {
// ggml_vk_init was not called in llama.cpp
// We might have had to fallback to CPU after load if the model is not possible to accelerate
// for instance if the quantization method is not supported on Vulkan yet
m_llModelInfo.fallbackReason = "model or quant has no GPU support";
modelLoadProps.insert("cpu_fallback_reason", "gpu_unsupported_model");
}
if (!success) {
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Could not load model due to invalid model file for %1"_s.arg(modelInfo.filename()));
modelLoadProps.insert("error", "loadmodel_failed");
return true;
}
switch (m_llModelInfo.model->implementation().modelType()[0]) {
case 'L': m_llModelType = LLModelType::LLAMA_; break;
case 'G': m_llModelType = LLModelType::GPTJ_; break;
default:
{
m_llModelInfo.resetModel(this);
if (!m_isServer)
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo));
resetModel();
emit modelLoadingError(u"Could not determine model type for %1"_s.arg(modelInfo.filename()));
}
}
modelLoadProps.insert("$duration", modelLoadTimer.elapsed() / 1000.);
return true;
};
bool ChatLLM::isModelLoaded() const
{
return m_llModelInfo.model && m_llModelInfo.model->isModelLoaded();

View File

@ -14,6 +14,7 @@
#include <QPair>
#include <QString>
#include <QThread>
#include <QVariantMap>
#include <QVector>
#include <QtGlobal>
@ -214,6 +215,8 @@ protected:
quint32 m_promptResponseTokens;
private:
bool loadNewModel(const ModelInfo &modelInfo, QVariantMap &modelLoadProps);
std::string m_response;
std::string m_nameResponse;
LLModelInfo m_llModelInfo;

View File

@ -26,6 +26,7 @@
#include <exception>
#include <utility>
#include <vector>
using namespace Qt::Literals::StringLiterals;
@ -63,9 +64,13 @@ void EmbeddingLLMWorker::wait()
bool EmbeddingLLMWorker::loadModel()
{
constexpr int n_ctx = 2048;
m_nomicAPIKey.clear();
m_model = nullptr;
// TODO(jared): react to setting changes without restarting
if (MySettings::globalInstance()->localDocsUseRemoteEmbed()) {
m_nomicAPIKey = MySettings::globalInstance()->localDocsNomicAPIKey();
return true;
@ -79,29 +84,86 @@ bool EmbeddingLLMWorker::loadModel()
QString filePath = embPathFmt.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL);
if (!QFileInfo::exists(filePath)) {
qWarning() << "WARNING: Local embedding model not found";
qWarning() << "embllm WARNING: Local embedding model not found";
return false;
}
QString requestedDevice = MySettings::globalInstance()->localDocsEmbedDevice();
std::string backend = "auto";
#ifdef Q_OS_MAC
if (requestedDevice == "Auto" || requestedDevice == "CPU")
backend = "cpu";
#else
if (requestedDevice.startsWith("CUDA: "))
backend = "cuda";
#endif
try {
m_model = LLModel::Implementation::construct(filePath.toStdString());
m_model = LLModel::Implementation::construct(filePath.toStdString(), backend, n_ctx);
} catch (const std::exception &e) {
qWarning() << "WARNING: Could not load embedding model:" << e.what();
qWarning() << "embllm WARNING: Could not load embedding model:" << e.what();
return false;
}
// NOTE: explicitly loads model on CPU to avoid GPU OOM
// TODO(cebtenzzre): support GPU-accelerated embeddings
bool success = m_model->loadModel(filePath.toStdString(), 2048, 0);
bool actualDeviceIsCPU = true;
#if defined(Q_OS_MAC) && defined(__aarch64__)
if (m_model->implementation().buildVariant() == "metal")
actualDeviceIsCPU = false;
#else
if (requestedDevice != "CPU") {
const LLModel::GPUDevice *device = nullptr;
std::vector<LLModel::GPUDevice> availableDevices = m_model->availableGPUDevices(0);
if (requestedDevice != "Auto") {
// Use the selected device
for (const LLModel::GPUDevice &d : availableDevices) {
if (QString::fromStdString(d.selectionName()) == requestedDevice) {
device = &d;
break;
}
}
}
std::string unavail_reason;
if (!device) {
// GPU not available
} else if (!m_model->initializeGPUDevice(device->index, &unavail_reason)) {
qWarning().noquote() << "embllm WARNING: Did not use GPU:" << QString::fromStdString(unavail_reason);
} else {
actualDeviceIsCPU = false;
}
}
#endif
bool success = m_model->loadModel(filePath.toStdString(), n_ctx, 100);
// CPU fallback
if (!actualDeviceIsCPU && !success) {
// llama_init_from_file returned nullptr
qWarning() << "embllm WARNING: Did not use GPU: GPU loading failed (out of VRAM?)";
if (backend == "cuda") {
// For CUDA, make sure we don't use the GPU at all - ngl=0 still offloads matmuls
try {
m_model = LLModel::Implementation::construct(filePath.toStdString(), "auto", n_ctx);
} catch (const std::exception &e) {
qWarning() << "embllm WARNING: Could not load embedding model:" << e.what();
return false;
}
}
success = m_model->loadModel(filePath.toStdString(), n_ctx, 0);
}
if (!success) {
qWarning() << "WARNING: Could not load embedding model";
qWarning() << "embllm WARNING: Could not load embedding model";
delete m_model;
m_model = nullptr;
return false;
}
if (!m_model->supportsEmbedding()) {
qWarning() << "WARNING: Model type does not support embeddings";
qWarning() << "embllm WARNING: Model type does not support embeddings";
delete m_model;
m_model = nullptr;
return false;
@ -128,7 +190,7 @@ std::vector<float> EmbeddingLLMWorker::generateQueryEmbedding(const QString &tex
std::vector<float> embedding(m_model->embeddingSize());
try {
m_model->embed({text.toStdString()}, embedding.data(), true);
m_model->embed({text.toStdString()}, embedding.data(), /*isRetrieval*/ true);
} catch (const std::exception &e) {
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
return {};
@ -203,26 +265,34 @@ void EmbeddingLLMWorker::docEmbeddingsRequested(const QVector<EmbeddingChunk> &c
if (!isNomic) {
QVector<EmbeddingResult> results;
results.reserve(chunks.size());
std::vector<std::string> texts;
texts.reserve(chunks.size());
for (const auto &c: chunks) {
EmbeddingResult result;
result.model = c.model;
result.folder_id = c.folder_id;
result.chunk_id = c.chunk_id;
// TODO(cebtenzzre): take advantage of batched embeddings
result.embedding.resize(m_model->embeddingSize());
{
QMutexLocker locker(&m_mutex);
try {
m_model->embed({c.chunk.toStdString()}, result.embedding.data(), false);
} catch (const std::exception &e) {
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
return;
}
}
results << result;
texts.push_back(c.chunk.toStdString());
}
constexpr int BATCH_SIZE = 4;
std::vector<float> result;
result.resize(chunks.size() * m_model->embeddingSize());
for (int j = 0; j < chunks.size(); j += BATCH_SIZE) {
QMutexLocker locker(&m_mutex);
std::vector batchTexts(texts.begin() + j, texts.begin() + std::min(j + BATCH_SIZE, int(texts.size())));
try {
m_model->embed(batchTexts, result.data() + j * m_model->embeddingSize(), /*isRetrieval*/ false);
} catch (const std::exception &e) {
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
return;
}
}
for (int i = 0; i < chunks.size(); i++)
memcpy(results[i].embedding.data(), &result[i * m_model->embeddingSize()], m_model->embeddingSize() * sizeof(float));
emit embeddingsGenerated(results);
return;
};

View File

@ -204,7 +204,7 @@ Window {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: MySettings.fontSize === "Small" ? 86 : 100
width: 16 + 52 * theme.fontScale
color: theme.viewBarBackground
ColumnLayout {
@ -213,20 +213,20 @@ Window {
anchors.topMargin: 30
anchors.horizontalCenter: parent.horizontalCenter
Layout.margins: 0
spacing: 18
spacing: 16
MyToolButton {
id: homeButton
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
backgroundColorHovered: theme.iconBackgroundViewBarHovered
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.preferredWidth: 38 * theme.fontScale
Layout.preferredHeight: 38 * theme.fontScale
Layout.alignment: Qt.AlignCenter
toggledWidth: 0
toggled: homeView.isShown()
toggledColor: theme.iconBackgroundViewBarToggled
imageWidth: 34
imageHeight: 34
imageWidth: 25 * theme.fontScale
imageHeight: 25 * theme.fontScale
source: "qrc:/gpt4all/icons/home.svg"
Accessible.name: qsTr("Home view")
Accessible.description: qsTr("Home view of application")
@ -238,10 +238,10 @@ Window {
Text {
Layout.topMargin: -20
text: qsTr("Home")
font.pixelSize: theme.fontSizeLargeCapped
font.pixelSize: theme.fontSizeMedium
font.bold: true
color: homeButton.hovered ? homeButton.backgroundColorHovered : homeButton.backgroundColor
Layout.preferredWidth: 48
Layout.preferredWidth: 38 * theme.fontScale
horizontalAlignment: Text.AlignHCenter
TapHandler {
onTapped: function(eventPoint, button) {
@ -254,14 +254,14 @@ Window {
id: chatButton
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
backgroundColorHovered: theme.iconBackgroundViewBarHovered
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.preferredWidth: 38 * theme.fontScale
Layout.preferredHeight: 38 * theme.fontScale
Layout.alignment: Qt.AlignCenter
toggledWidth: 0
toggled: chatView.isShown()
toggledColor: theme.iconBackgroundViewBarToggled
imageWidth: 34
imageHeight: 34
imageWidth: 25 * theme.fontScale
imageHeight: 25 * theme.fontScale
source: "qrc:/gpt4all/icons/chat.svg"
Accessible.name: qsTr("Chat view")
Accessible.description: qsTr("Chat view to interact with models")
@ -273,10 +273,10 @@ Window {
Text {
Layout.topMargin: -20
text: qsTr("Chats")
font.pixelSize: theme.fontSizeLargeCapped
font.pixelSize: theme.fontSizeMedium
font.bold: true
color: chatButton.hovered ? chatButton.backgroundColorHovered : chatButton.backgroundColor
Layout.preferredWidth: 48
Layout.preferredWidth: 38 * theme.fontScale
horizontalAlignment: Text.AlignHCenter
TapHandler {
onTapped: function(eventPoint, button) {
@ -289,13 +289,13 @@ Window {
id: modelsButton
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
backgroundColorHovered: theme.iconBackgroundViewBarHovered
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.preferredWidth: 38 * theme.fontScale
Layout.preferredHeight: 38 * theme.fontScale
toggledWidth: 0
toggled: modelsView.isShown()
toggledColor: theme.iconBackgroundViewBarToggled
imageWidth: 34
imageHeight: 34
imageWidth: 25 * theme.fontScale
imageHeight: 25 * theme.fontScale
source: "qrc:/gpt4all/icons/models.svg"
Accessible.name: qsTr("Models")
Accessible.description: qsTr("Models view for installed models")
@ -307,10 +307,10 @@ Window {
Text {
Layout.topMargin: -20
text: qsTr("Models")
font.pixelSize: theme.fontSizeLargeCapped
font.pixelSize: theme.fontSizeMedium
font.bold: true
color: modelsButton.hovered ? modelsButton.backgroundColorHovered : modelsButton.backgroundColor
Layout.preferredWidth: 48
Layout.preferredWidth: 38 * theme.fontScale
horizontalAlignment: Text.AlignHCenter
TapHandler {
onTapped: function(eventPoint, button) {
@ -323,13 +323,13 @@ Window {
id: localdocsButton
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
backgroundColorHovered: theme.iconBackgroundViewBarHovered
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.preferredWidth: 38 * theme.fontScale
Layout.preferredHeight: 38 * theme.fontScale
toggledWidth: 0
toggledColor: theme.iconBackgroundViewBarToggled
toggled: localDocsView.isShown()
imageWidth: 34
imageHeight: 34
imageWidth: 25 * theme.fontScale
imageHeight: 25 * theme.fontScale
source: "qrc:/gpt4all/icons/db.svg"
Accessible.name: qsTr("LocalDocs")
Accessible.description: qsTr("LocalDocs view to configure and use local docs")
@ -341,10 +341,10 @@ Window {
Text {
Layout.topMargin: -20
text: qsTr("LocalDocs")
font.pixelSize: theme.fontSizeLargeCapped
font.pixelSize: theme.fontSizeMedium
font.bold: true
color: localdocsButton.hovered ? localdocsButton.backgroundColorHovered : localdocsButton.backgroundColor
Layout.preferredWidth: 48
Layout.preferredWidth: 38 * theme.fontScale
horizontalAlignment: Text.AlignHCenter
TapHandler {
onTapped: function(eventPoint, button) {
@ -357,13 +357,13 @@ Window {
id: settingsButton
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
backgroundColorHovered: theme.iconBackgroundViewBarHovered
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.preferredWidth: 38 * theme.fontScale
Layout.preferredHeight: 38 * theme.fontScale
toggledWidth: 0
toggledColor: theme.iconBackgroundViewBarToggled
toggled: settingsView.isShown()
imageWidth: 34
imageHeight: 34
imageWidth: 25 * theme.fontScale
imageHeight: 25 * theme.fontScale
source: "qrc:/gpt4all/icons/settings.svg"
Accessible.name: qsTr("Settings")
Accessible.description: qsTr("Settings view for application configuration")
@ -375,10 +375,10 @@ Window {
Text {
Layout.topMargin: -20
text: qsTr("Settings")
font.pixelSize: theme.fontSizeLargeCapped
font.pixelSize: theme.fontSizeMedium
font.bold: true
color: settingsButton.hovered ? settingsButton.backgroundColorHovered : settingsButton.backgroundColor
Layout.preferredWidth: 48
Layout.preferredWidth: 38 * theme.fontScale
horizontalAlignment: Text.AlignHCenter
TapHandler {
onTapped: function(eventPoint, button) {

View File

@ -47,6 +47,7 @@ static const QVariantMap basicDefaults {
{ "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } },
{ "localdocs/useRemoteEmbed", false },
{ "localdocs/nomicAPIKey", "" },
{ "localdocs/embedDevice", "Auto" },
{ "network/attribution", "" },
};
@ -77,6 +78,22 @@ static QString defaultLocalModelsPath()
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;
}
class MyPrivateSettings: public MySettings { };
Q_GLOBAL_STATIC(MyPrivateSettings, settingsInstance)
MySettings *MySettings::globalInstance()
@ -85,18 +102,10 @@ MySettings *MySettings::globalInstance()
}
MySettings::MySettings()
: QObject{nullptr}
: QObject(nullptr)
, m_deviceList(getDevices())
, m_embeddingsDeviceList(getDevices(/*skipKompute*/ true))
{
QVector<QString> 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)
deviceList << QString::fromStdString(d.selectionName());
#endif
deviceList << "CPU";
setDeviceList(deviceList);
}
QVariant MySettings::getBasicSetting(const QString &name) const
@ -113,17 +122,6 @@ void MySettings::setBasicSetting(const QString &name, const QVariant &value, std
QMetaObject::invokeMethod(this, u"%1Changed"_s.arg(signal.value_or(name)).toLatin1().constData());
}
Q_INVOKABLE QVector<QString> MySettings::deviceList() const
{
return m_deviceList;
}
void MySettings::setDeviceList(const QVector<QString> &value)
{
m_deviceList = value;
emit deviceListChanged();
}
void MySettings::restoreModelDefaults(const ModelInfo &info)
{
setModelTemperature(info, info.m_temperature);
@ -162,6 +160,7 @@ void MySettings::restoreLocalDocsDefaults()
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)
@ -382,6 +381,7 @@ bool MySettings::localDocsShowReferences() const { return getBasicSetting
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(); }
void MySettings::setSaveChatsContext(bool value) { setBasicSetting("saveChatsContext", value); }
@ -397,6 +397,7 @@ void MySettings::setLocalDocsShowReferences(bool value) { setBasic
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"); }
QString MySettings::modelPath()
@ -446,11 +447,10 @@ QString MySettings::device()
void MySettings::setDevice(const QString &value)
{
if (device() == value)
return;
m_settings.setValue("device", value);
emit deviceChanged();
if (device() != value) {
m_settings.setValue("device", value);
emit deviceChanged();
}
}
bool MySettings::forceMetal() const
@ -460,10 +460,10 @@ bool MySettings::forceMetal() const
void MySettings::setForceMetal(bool value)
{
if (m_forceMetal == value)
return;
m_forceMetal = value;
emit forceMetalChanged(value);
if (m_forceMetal != value) {
m_forceMetal = value;
emit forceMetalChanged(value);
}
}
bool MySettings::networkIsActive() const

View File

@ -31,11 +31,13 @@ class MySettings : public QObject
Q_PROPERTY(QStringList localDocsFileExtensions READ localDocsFileExtensions WRITE setLocalDocsFileExtensions NOTIFY localDocsFileExtensionsChanged)
Q_PROPERTY(bool localDocsUseRemoteEmbed READ localDocsUseRemoteEmbed WRITE setLocalDocsUseRemoteEmbed NOTIFY localDocsUseRemoteEmbedChanged)
Q_PROPERTY(QString localDocsNomicAPIKey READ localDocsNomicAPIKey WRITE setLocalDocsNomicAPIKey NOTIFY localDocsNomicAPIKeyChanged)
Q_PROPERTY(QString localDocsEmbedDevice READ localDocsEmbedDevice WRITE setLocalDocsEmbedDevice NOTIFY localDocsEmbedDeviceChanged)
Q_PROPERTY(QString networkAttribution READ networkAttribution WRITE setNetworkAttribution NOTIFY networkAttributionChanged)
Q_PROPERTY(bool networkIsActive READ networkIsActive WRITE setNetworkIsActive NOTIFY networkIsActiveChanged)
Q_PROPERTY(bool networkUsageStatsActive READ networkUsageStatsActive WRITE setNetworkUsageStatsActive NOTIFY networkUsageStatsActiveChanged)
Q_PROPERTY(QString device READ device WRITE setDevice NOTIFY deviceChanged)
Q_PROPERTY(QVector<QString> deviceList READ deviceList NOTIFY deviceListChanged)
Q_PROPERTY(QStringList deviceList MEMBER m_deviceList CONSTANT)
Q_PROPERTY(QStringList embeddingsDeviceList MEMBER m_embeddingsDeviceList CONSTANT)
Q_PROPERTY(int networkPort READ networkPort WRITE setNetworkPort NOTIFY networkPortChanged)
public:
@ -138,6 +140,8 @@ public:
void setLocalDocsUseRemoteEmbed(bool value);
QString localDocsNomicAPIKey() const;
void setLocalDocsNomicAPIKey(const QString &value);
QString localDocsEmbedDevice() const;
void setLocalDocsEmbedDevice(const QString &value);
// Network settings
QString networkAttribution() const;
@ -151,9 +155,6 @@ public:
int networkPort() const;
void setNetworkPort(int value);
QVector<QString> deviceList() const;
void setDeviceList(const QVector<QString> &value);
Q_SIGNALS:
void nameChanged(const ModelInfo &info);
void filenameChanged(const ModelInfo &info);
@ -185,18 +186,19 @@ Q_SIGNALS:
void localDocsFileExtensionsChanged();
void localDocsUseRemoteEmbedChanged();
void localDocsNomicAPIKeyChanged();
void localDocsEmbedDeviceChanged();
void networkAttributionChanged();
void networkIsActiveChanged();
void networkPortChanged();
void networkUsageStatsActiveChanged();
void attemptModelLoadChanged();
void deviceChanged();
void deviceListChanged();
private:
QSettings m_settings;
bool m_forceMetal;
QVector<QString> m_deviceList;
const QStringList m_deviceList;
const QStringList m_embeddingsDeviceList;
private:
explicit MySettings();

View File

@ -603,13 +603,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("File size")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: filesize
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -625,13 +625,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("RAM required")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -647,13 +647,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Parameters")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: parameters !== "" ? parameters : "?"
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -669,13 +669,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Quant")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: quant
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -691,13 +691,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Type")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: type
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}

View File

@ -62,9 +62,19 @@ MySettingsTab {
rowSpacing: 30
columnSpacing: 10
ColumnLayout {
Label {
Layout.row: 0
Layout.column: 0
Layout.bottomMargin: 10
color: theme.settingsTitleTextColor
font.pixelSize: theme.fontSizeBannerSmall
font.bold: true
text: qsTr("Application Settings")
}
ColumnLayout {
Layout.row: 1
Layout.column: 0
Layout.columnSpan: 3
Layout.fillWidth: true
spacing: 10
@ -72,7 +82,7 @@ MySettingsTab {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "General"
text: qsTr("General")
}
Rectangle {
@ -85,22 +95,21 @@ MySettingsTab {
MySettingsLabel {
id: themeLabel
text: qsTr("Theme")
helpText: qsTr("Customize the colors of GPT4All")
Layout.row: 1
helpText: qsTr("The application color scheme.")
Layout.row: 2
Layout.column: 0
}
MyComboBox {
id: themeBox
Layout.row: 1
Layout.row: 2
Layout.column: 2
Layout.minimumWidth: 200
Layout.maximumWidth: 200
Layout.fillWidth: false
Layout.alignment: Qt.AlignRight
model: [qsTr("Dark"), qsTr("Light"), qsTr("LegacyDark")]
Accessible.role: Accessible.ComboBox
Accessible.name: qsTr("Color theme")
Accessible.description: qsTr("Color theme for the chat client to use")
Accessible.name: themeLabel.text
Accessible.description: themeLabel.helpText
function updateModel() {
themeBox.currentIndex = themeBox.indexOfValue(MySettings.chatTheme);
}
@ -120,22 +129,21 @@ MySettingsTab {
MySettingsLabel {
id: fontLabel
text: qsTr("Font Size")
helpText: qsTr("How big your font is displayed")
Layout.row: 2
helpText: qsTr("The size of text in the application.")
Layout.row: 3
Layout.column: 0
}
MyComboBox {
id: fontBox
Layout.row: 2
Layout.row: 3
Layout.column: 2
Layout.minimumWidth: 200
Layout.maximumWidth: 200
Layout.fillWidth: false
Layout.alignment: Qt.AlignRight
model: ["Small", "Medium", "Large"]
Accessible.role: Accessible.ComboBox
Accessible.name: qsTr("Font size")
Accessible.description: qsTr("Font size of the chat client")
Accessible.name: fontLabel.text
Accessible.description: fontLabel.helpText
function updateModel() {
fontBox.currentIndex = fontBox.indexOfValue(MySettings.fontSize);
}
@ -155,59 +163,54 @@ MySettingsTab {
MySettingsLabel {
id: deviceLabel
text: qsTr("Device")
helpText: qsTr("The hardware device used to load the model")
Layout.row: 3
helpText: qsTr('The compute device used for text generation. "Auto" uses Vulkan or Metal.')
Layout.row: 4
Layout.column: 0
}
MyComboBox {
id: deviceBox
Layout.row: 3
Layout.row: 4
Layout.column: 2
Layout.minimumWidth: 400
Layout.maximumWidth: 400
Layout.fillWidth: false
Layout.alignment: Qt.AlignRight
model: MySettings.deviceList
Accessible.role: Accessible.ComboBox
Accessible.name: qsTr("Device")
Accessible.description: qsTr("Device of the chat client")
Accessible.name: deviceLabel.text
Accessible.description: deviceLabel.helpText
function updateModel() {
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device);
}
Component.onCompleted: {
deviceBox.updateModel()
deviceBox.updateModel();
}
Connections {
target: MySettings
function onDeviceChanged() {
deviceBox.updateModel()
}
function onDeviceListChanged() {
deviceBox.updateModel()
deviceBox.updateModel();
}
}
onActivated: {
MySettings.device = deviceBox.currentText
MySettings.device = deviceBox.currentText;
}
}
MySettingsLabel {
id: defaultModelLabel
text: qsTr("Default model")
helpText: qsTr("The preferred default model")
Layout.row: 4
text: qsTr("Default Model")
helpText: qsTr("The preferred model for new chats. Also used as the local server fallback.")
Layout.row: 5
Layout.column: 0
}
MyComboBox {
id: comboBox
Layout.row: 4
Layout.row: 5
Layout.column: 2
Layout.minimumWidth: 400
Layout.maximumWidth: 400
Layout.alignment: Qt.AlignRight
model: ModelList.userDefaultModelList
Accessible.role: Accessible.ComboBox
Accessible.name: qsTr("Default model")
Accessible.description: qsTr("Default model to use; the first item is the current default model")
Accessible.name: defaultModelLabel.text
Accessible.description: defaultModelLabel.helpText
function updateModel() {
comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel);
}
@ -226,14 +229,14 @@ MySettingsTab {
}
MySettingsLabel {
id: modelPathLabel
text: qsTr("Download path")
helpText: qsTr("The download folder for models")
Layout.row: 5
text: qsTr("Download Path")
helpText: qsTr("Where to store local models and the LocalDocs database.")
Layout.row: 6
Layout.column: 0
}
RowLayout {
Layout.row: 5
Layout.row: 6
Layout.column: 2
Layout.alignment: Qt.AlignRight
Layout.minimumWidth: 400
@ -245,11 +248,8 @@ MySettingsTab {
font.pixelSize: theme.fontSizeLarge
implicitWidth: 300
Layout.fillWidth: true
ToolTip.text: qsTr("Path where model files will be downloaded to")
ToolTip.visible: hovered
Accessible.role: Accessible.ToolTip
Accessible.name: modelPathDisplayField.text
Accessible.description: ToolTip.text
Accessible.name: modelPathLabel.text
Accessible.description: modelPathLabel.helpText
onEditingFinished: {
if (isValid) {
MySettings.modelPath = modelPathDisplayField.text
@ -271,29 +271,32 @@ MySettingsTab {
MySettingsLabel {
id: dataLakeLabel
text: qsTr("Opensource Datalake")
helpText: qsTr("Send your data to the GPT4All Open Source Datalake.")
Layout.row: 6
text: qsTr("Enable Datalake")
helpText: qsTr("Send chats and feedback to the GPT4All Open-Source Datalake.")
Layout.row: 7
Layout.column: 0
}
MyCheckBox {
id: dataLakeBox
Layout.row: 6
Layout.row: 7
Layout.column: 2
Layout.alignment: Qt.AlignRight
checked: MySettings.networkIsActive
onClicked: {
if (MySettings.networkIsActive) {
MySettings.networkIsActive = false
} else
networkDialog.open()
Component.onCompleted: { dataLakeBox.checked = MySettings.networkIsActive; }
Connections {
target: MySettings
function onNetworkIsActiveChanged() { dataLakeBox.checked = MySettings.networkIsActive; }
}
onClicked: {
if (MySettings.networkIsActive)
MySettings.networkIsActive = false;
else
networkDialog.open();
dataLakeBox.checked = MySettings.networkIsActive;
}
ToolTip.text: qsTr("Reveals a dialogue where you can opt-in for sharing data over network")
ToolTip.visible: hovered
}
ColumnLayout {
Layout.row: 7
Layout.row: 8
Layout.column: 0
Layout.columnSpan: 3
Layout.fillWidth: true
@ -302,7 +305,7 @@ MySettingsTab {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "Advanced"
text: qsTr("Advanced")
}
Rectangle {
@ -315,18 +318,16 @@ MySettingsTab {
MySettingsLabel {
id: nThreadsLabel
text: qsTr("CPU Threads")
helpText: qsTr("Number of CPU threads for inference and embedding")
Layout.row: 8
helpText: qsTr("The number of CPU threads used for inference and embedding.")
Layout.row: 9
Layout.column: 0
}
MyTextField {
text: MySettings.threadCount
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Amount of processing threads to use bounded by 1 and number of logical processors")
ToolTip.visible: hovered
Layout.alignment: Qt.AlignRight
Layout.row: 8
Layout.row: 9
Layout.column: 2
Layout.minimumWidth: 200
Layout.maximumWidth: 200
@ -348,47 +349,43 @@ MySettingsTab {
}
MySettingsLabel {
id: saveChatsContextLabel
text: qsTr("Save chat context")
helpText: qsTr("Save chat context to disk")
Layout.row: 9
text: qsTr("Save Chat Context")
helpText: qsTr("Save the chat model's state to disk for faster loading. WARNING: Uses ~2GB per chat.")
Layout.row: 10
Layout.column: 0
}
MyCheckBox {
id: saveChatsContextBox
Layout.row: 9
Layout.row: 10
Layout.column: 2
Layout.alignment: Qt.AlignRight
checked: MySettings.saveChatsContext
onClicked: {
MySettings.saveChatsContext = !MySettings.saveChatsContext
}
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
ToolTip.visible: hovered
}
MySettingsLabel {
id: serverChatLabel
text: qsTr("Enable API server")
helpText: qsTr("A local http server running on local port")
Layout.row: 10
text: qsTr("Enable Local Server")
helpText: qsTr("Expose an OpenAI-Compatible server to localhost. WARNING: Results in increased resource usage.")
Layout.row: 11
Layout.column: 0
}
MyCheckBox {
id: serverChatBox
Layout.row: 10
Layout.row: 11
Layout.column: 2
Layout.alignment: Qt.AlignRight
checked: MySettings.serverChat
onClicked: {
MySettings.serverChat = !MySettings.serverChat
}
ToolTip.text: qsTr("WARNING: This enables the gui to act as a local REST web server(OpenAI API compliant) for API requests and will increase your RAM usage as well")
ToolTip.visible: hovered
}
MySettingsLabel {
id: serverPortLabel
text: qsTr("API Server Port:")
helpText: qsTr("A local port to run the server (Requires restart")
Layout.row: 11
text: qsTr("API Server Port")
helpText: qsTr("The port to use for the local server. Requires restart.")
Layout.row: 12
Layout.column: 0
}
MyTextField {
@ -396,9 +393,7 @@ MySettingsTab {
text: MySettings.networkPort
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Api server port. WARNING: You need to restart the application for it to take effect")
ToolTip.visible: hovered
Layout.row: 11
Layout.row: 12
Layout.column: 2
Layout.minimumWidth: 200
Layout.maximumWidth: 200
@ -416,8 +411,8 @@ MySettingsTab {
}
}
Accessible.role: Accessible.EditableText
Accessible.name: serverPortField.text
Accessible.description: ToolTip.text
Accessible.name: serverPortLabel.text
Accessible.description: serverPortLabel.helpText
}
/*MySettingsLabel {
@ -441,8 +436,8 @@ MySettingsTab {
MySettingsLabel {
id: updatesLabel
text: qsTr("Check for updates")
helpText: qsTr("Click to see if an update to the application is available");
text: qsTr("Check For Updates")
helpText: qsTr("Manually check for an update to GPT4All.");
Layout.row: 14
Layout.column: 0
}

View File

@ -110,7 +110,7 @@ Rectangle {
bottomPadding: 5
text: parent.section
color: theme.chatDrawerSectionHeader
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmallest
}
}
}

View File

@ -365,7 +365,6 @@ Rectangle {
}
}
Accessible.role: Accessible.ComboBox
Accessible.name: currentModelName()
Accessible.description: qsTr("The top item is the current model")
onActivated: function (index) {

View File

@ -89,7 +89,7 @@ Rectangle {
text: "%1 %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
elide: Text.ElideRight
color: theme.mutedTextColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
RowLayout {
visible: model.updating
@ -105,7 +105,7 @@ Rectangle {
text: qsTr("Updating")
elide: Text.ElideRight
color: theme.accentColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}

View File

@ -36,6 +36,7 @@ Rectangle {
Layout.fillWidth: true
Layout.maximumWidth: 1530
Layout.alignment: Qt.AlignCenter
Layout.topMargin: 20
spacing: 30
ColumnLayout {

View File

@ -19,20 +19,30 @@ MySettingsTab {
title: qsTr("LocalDocs")
contentItem: ColumnLayout {
id: root
spacing: 10
spacing: 30
Label {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
Layout.bottomMargin: 10
color: theme.settingsTitleTextColor
font.pixelSize: theme.fontSizeBannerSmall
font.bold: true
text: "Indexing"
text: qsTr("LocalDocs Settings")
}
Rectangle {
Layout.bottomMargin: 15
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
ColumnLayout {
spacing: 10
Label {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: qsTr("Indexing")
}
Rectangle {
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
}
}
RowLayout {
@ -81,25 +91,26 @@ MySettingsTab {
}
}
Label {
Layout.topMargin: 15
color: theme.grayRed900
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "Embedding"
}
ColumnLayout {
spacing: 10
Label {
color: theme.grayRed900
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: qsTr("Embedding")
}
Rectangle {
Layout.bottomMargin: 15
Layout.fillWidth: true
height: 1
color: theme.grayRed500
Rectangle {
Layout.fillWidth: true
height: 1
color: theme.grayRed500
}
}
RowLayout {
MySettingsLabel {
text: qsTr("Use Nomic Embed API")
helpText: qsTr("Embed documents using the fast Nomic API instead of a private local model.")
helpText: qsTr("Embed documents using the fast Nomic API instead of a private local model. Requires restart.")
}
MyCheckBox {
@ -113,11 +124,45 @@ MySettingsTab {
}
}
RowLayout {
MySettingsLabel {
id: deviceLabel
text: qsTr("Embeddings Device")
helpText: qsTr('The compute device used for embeddings. "Auto" uses the CPU. Requires restart.')
}
MyComboBox {
id: deviceBox
enabled: !useNomicAPIBox.checked
Layout.minimumWidth: 400
Layout.maximumWidth: 400
Layout.fillWidth: false
Layout.alignment: Qt.AlignRight
model: MySettings.embeddingsDeviceList
Accessible.name: deviceLabel.text
Accessible.description: deviceLabel.helpText
function updateModel() {
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.localDocsEmbedDevice);
}
Component.onCompleted: {
deviceBox.updateModel();
}
Connections {
target: MySettings
function onDeviceChanged() {
deviceBox.updateModel();
}
}
onActivated: {
MySettings.localDocsEmbedDevice = deviceBox.currentText;
}
}
}
RowLayout {
MySettingsLabel {
id: apiKeyLabel
text: qsTr("Nomic API Key")
helpText: qsTr('API key to use for Nomic Embed. Get one from the Atlas <a href="https://atlas.nomic.ai/cli-login">API keys page</a>.')
helpText: qsTr('API key to use for Nomic Embed. Get one from the Atlas <a href="https://atlas.nomic.ai/cli-login">API keys page</a>. Requires restart.')
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
}
@ -148,26 +193,27 @@ MySettingsTab {
}
}
Label {
Layout.topMargin: 15
color: theme.grayRed900
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "Display"
}
ColumnLayout {
spacing: 10
Label {
color: theme.grayRed900
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: qsTr("Display")
}
Rectangle {
Layout.bottomMargin: 15
Layout.fillWidth: true
height: 1
color: theme.grayRed500
Rectangle {
Layout.fillWidth: true
height: 1
color: theme.grayRed500
}
}
RowLayout {
MySettingsLabel {
id: showReferencesLabel
text: qsTr("Show sources")
helpText: qsTr("Shows sources in GUI generated by localdocs")
text: qsTr("Show Sources")
helpText: qsTr("Display the sources used for each response.")
}
MyCheckBox {
id: showReferencesBox
@ -178,19 +224,20 @@ MySettingsTab {
}
}
Label {
Layout.topMargin: 15
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "Advanced"
}
ColumnLayout {
spacing: 10
Label {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: qsTr("Advanced")
}
Rectangle {
Layout.bottomMargin: 15
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
Rectangle {
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
}
}
MySettingsLabel {

View File

@ -307,7 +307,7 @@ Rectangle {
}
elide: Text.ElideRight
color: theme.mutedDarkTextColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
Text {
visible: {
@ -322,7 +322,7 @@ Rectangle {
elide: Text.ElideRight
color: theme.mutedDarkTextColor
font.family: "monospace"
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
}
@ -332,21 +332,21 @@ Rectangle {
text: "%1 %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
elide: Text.ElideRight
color: theme.styledTextColor2
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
Text {
text: model.embeddingModel
elide: Text.ElideRight
color: theme.mutedDarkTextColor
font.bold: true
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
Text {
visible: Qt.formatDateTime(model.lastUpdate) !== ""
text: Qt.formatDateTime(model.lastUpdate)
elide: Text.ElideRight
color: theme.mutedTextColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
Text {
visible: model.currentEmbeddingsToIndex !== 0
@ -354,7 +354,7 @@ Rectangle {
+ model.totalEmbeddingsToIndex + " embeddings"
elide: Text.ElideRight
color: theme.mutedTextColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
}
}
@ -400,53 +400,29 @@ Rectangle {
Layout.fillWidth: true
spacing: 30
Layout.leftMargin: 15
Layout.rightMargin: 15
Layout.topMargin: 15
Text {
MyTextButton {
text: qsTr("Remove")
elide: Text.ElideRight
color: theme.red500
font.bold: true
font.pixelSize: theme.fontSizeSmall
TapHandler {
onTapped: {
LocalDocs.removeFolder(collection, folder_path)
}
}
}
Text {
Layout.alignment: Qt.AlignRight
visible: !model.forceIndexing && !model.indexing && model.currentEmbeddingsToIndex === 0
text: qsTr("Rebuild")
elide: Text.ElideRight
color: theme.red500
font.bold: true
font.pixelSize: theme.fontSizeSmall
TapHandler {
onTapped: { LocalDocs.forceRebuildFolder(folder_path); }
}
HoverHandler { id: hoverHandler1 }
ToolTip.text: qsTr("Reindex this folder from scratch. This is slow and usually not needed.")
ToolTip.visible: hoverHandler1.hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
onClick: LocalDocs.removeFolder(collection, folder_path)
}
Item {
Layout.fillWidth: true
}
Text {
Layout.alignment: Qt.AlignRight
MyTextButton {
visible: !model.forceIndexing && !model.indexing && model.currentEmbeddingsToIndex === 0
text: qsTr("Rebuild")
color: theme.green500
onClick: { LocalDocs.forceRebuildFolder(folder_path); }
tooltip: qsTr("Reindex this folder from scratch. This is slow and usually not needed.")
}
MyTextButton {
visible: model.forceIndexing
text: qsTr("Update")
elide: Text.ElideRight
color: theme.red500
font.bold: true
font.pixelSize: theme.fontSizeSmall
TapHandler {
onTapped: { LocalDocs.forceIndexing(collection); }
}
HoverHandler { id: hoverHandler2 }
ToolTip.text: qsTr("Update the collection to the new version. This is a slow operation.")
ToolTip.visible: hoverHandler2.hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
color: theme.green500
onClick: { LocalDocs.forceIndexing(collection); }
tooltip: qsTr("Update the collection to the new version. This is a slow operation.")
}
}
}

View File

@ -11,7 +11,7 @@ MySettingsTab {
onRestoreDefaultsClicked: {
MySettings.restoreModelDefaults(root.currentModelInfo);
}
title: qsTr("Model/Character Settings")
title: qsTr("Model")
contentItem: GridLayout {
id: root
columns: 3
@ -23,32 +23,14 @@ MySettingsTab {
property var currentModelId: comboBox.currentValue
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
ColumnLayout {
Layout.row: 0
Layout.column: 0
Layout.columnSpan: 3
Layout.fillWidth: true
spacing: 10
Label {
color: theme.styledTextColor
font.pixelSize: theme.fontSizeLarge
font.bold: true
text: "General"
}
Rectangle {
Layout.fillWidth: true
height: 1
color: theme.settingsDivider
}
}
MySettingsLabel {
id: label
Label {
Layout.row: 1
Layout.column: 0
text: qsTr("Model/Character")
helpText: qsTr("Select or clone a model and change its settings")
Layout.bottomMargin: 10
color: theme.settingsTitleTextColor
font.pixelSize: theme.fontSizeBannerSmall
font.bold: true
text: qsTr("Model Settings")
}
RowLayout {
@ -56,7 +38,6 @@ MySettingsTab {
Layout.row: 2
Layout.column: 0
Layout.columnSpan: 2
height: label.height + 20
spacing: 10
MyComboBox {
@ -122,9 +103,7 @@ MySettingsTab {
Layout.topMargin: 15
spacing: 10
MySettingsLabel {
id: uniqueNameLabel
text: qsTr("Unique Name")
helpText: qsTr("Must contain a non-empty unique name")
text: qsTr("Name")
}
}
@ -158,7 +137,6 @@ MySettingsTab {
MySettingsLabel {
text: qsTr("Model File")
helpText: qsTr("The filename of the selected model")
Layout.row: 5
Layout.column: 0
Layout.topMargin: 15
@ -177,7 +155,7 @@ MySettingsTab {
MySettingsLabel {
visible: !root.currentModelInfo.isOnline
text: qsTr("System Prompt")
helpText: qsTr("Prefixed at the beginning of every conversation")
helpText: qsTr("Prefixed at the beginning of every conversation. Must contain the appropriate framing tokens.")
Layout.row: 7
Layout.column: 0
Layout.topMargin: 15
@ -212,9 +190,6 @@ MySettingsTab {
MySettings.setModelSystemPrompt(root.currentModelInfo, text)
}
Accessible.role: Accessible.EditableText
ToolTip.text: qsTr("The systemPrompt allows instructions to the model at the beginning of a chat.\nNOTE: A longer, detailed system prompt can lead to higher quality answers, but can also slow down generation.")
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
}
}
@ -227,7 +202,7 @@ MySettingsTab {
MySettingsLabel {
id: promptTemplateLabel
text: qsTr("Prompt Template")
helpText: qsTr("The template that wraps every prompt")
helpText: qsTr("The template that wraps every prompt.")
}
MySettingsLabel {
id: promptTemplateLabelHelp
@ -271,9 +246,6 @@ MySettingsTab {
Accessible.role: Accessible.EditableText
Accessible.name: promptTemplateLabel.text
Accessible.description: promptTemplateLabelHelp.text
ToolTip.text: qsTr("The prompt template partially determines how models will respond to prompts.\nNOTE: A longer, detailed template can lead to higher quality answers, but can also slow down generation.")
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
}
}
@ -328,7 +300,7 @@ MySettingsTab {
id: contextLengthLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Context Length")
helpText: qsTr("Conversation context window")
helpText: qsTr("Number of input and output tokens the model sees.")
Layout.row: 0
Layout.column: 0
}
@ -378,7 +350,7 @@ MySettingsTab {
MySettingsLabel {
id: tempLabel
text: qsTr("Temperature")
helpText: qsTr("The temperature for model token generation")
helpText: qsTr("Randomness of model output. Higher -> more variation.")
Layout.row: 1
Layout.column: 2
}
@ -422,8 +394,8 @@ MySettingsTab {
}
MySettingsLabel {
id: topPLabel
text: qsTr("Top P")
helpText: qsTr("Prevents choosing highly unlikely tokens")
text: qsTr("Top-P")
helpText: qsTr("Nucleus Sampling factor. Lower -> more predicatable.")
Layout.row: 2
Layout.column: 0
}
@ -432,7 +404,7 @@ MySettingsTab {
text: root.currentModelInfo.topP
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens, aka Nucleus Sampling")
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens.")
ToolTip.visible: hovered
Layout.row: 2
Layout.column: 1
@ -466,8 +438,8 @@ MySettingsTab {
}
MySettingsLabel {
id: minPLabel
text: qsTr("Min P")
helpText: qsTr("Minimum relative probability")
text: qsTr("Min-P")
helpText: qsTr("Minimum token probability. Higher -> more predictable.")
Layout.row: 3
Layout.column: 0
}
@ -512,8 +484,8 @@ MySettingsTab {
MySettingsLabel {
id: topKLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Top K")
helpText: qsTr("Size of selection pool for tokens")
text: qsTr("Top-K")
helpText: qsTr("Size of selection pool for tokens.")
Layout.row: 2
Layout.column: 2
}
@ -523,7 +495,7 @@ MySettingsTab {
text: root.currentModelInfo.topK
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from")
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from.")
ToolTip.visible: hovered
Layout.row: 2
Layout.column: 3
@ -559,7 +531,7 @@ MySettingsTab {
id: maxLengthLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Max Length")
helpText: qsTr("Maximum length of response in tokens")
helpText: qsTr("Maximum response length, in tokens.")
Layout.row: 0
Layout.column: 2
}
@ -569,8 +541,6 @@ MySettingsTab {
text: root.currentModelInfo.maxLength
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Maximum length of response in tokens")
ToolTip.visible: hovered
Layout.row: 0
Layout.column: 3
validator: IntValidator {
@ -606,7 +576,7 @@ MySettingsTab {
id: batchSizeLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Prompt Batch Size")
helpText: qsTr("Amount of prompt tokens to process at once")
helpText: qsTr("The batch size used for prompt processing.")
Layout.row: 1
Layout.column: 0
}
@ -616,7 +586,7 @@ MySettingsTab {
text: root.currentModelInfo.promptBatchSize
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM")
ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM.")
ToolTip.visible: hovered
Layout.row: 1
Layout.column: 1
@ -652,7 +622,7 @@ MySettingsTab {
id: repeatPenaltyLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Repeat Penalty")
helpText: qsTr("Penalize repetitiveness")
helpText: qsTr("Repetition penalty factor. Set to 1 to disable.")
Layout.row: 4
Layout.column: 2
}
@ -662,8 +632,6 @@ MySettingsTab {
text: root.currentModelInfo.repeatPenalty
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
ToolTip.visible: hovered
Layout.row: 4
Layout.column: 3
validator: DoubleValidator {
@ -698,7 +666,7 @@ MySettingsTab {
id: repeatPenaltyTokensLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("Repeat Penalty Tokens")
helpText: qsTr("Length to apply penalty")
helpText: qsTr("Number of previous tokens used for penalty.")
Layout.row: 3
Layout.column: 2
}
@ -708,8 +676,6 @@ MySettingsTab {
text: root.currentModelInfo.repeatPenaltyTokens
color: theme.textColor
font.pixelSize: theme.fontSizeLarge
ToolTip.text: qsTr("How far back in output to apply repeat penalty")
ToolTip.visible: hovered
Layout.row: 3
Layout.column: 3
validator: IntValidator {
@ -745,7 +711,7 @@ MySettingsTab {
id: gpuLayersLabel
visible: !root.currentModelInfo.isOnline
text: qsTr("GPU Layers")
helpText: qsTr("How many GPU layers to load into VRAM")
helpText: qsTr("Number of model layers to load into VRAM.")
Layout.row: 4
Layout.column: 0
}
@ -755,7 +721,7 @@ MySettingsTab {
text: root.currentModelInfo.gpuLayers
font.pixelSize: theme.fontSizeLarge
color: theme.textColor
ToolTip.text: qsTr("How many GPU layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
ToolTip.text: qsTr("How many model layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
ToolTip.visible: hovered
Layout.row: 4
Layout.column: 1

View File

@ -180,13 +180,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("File size")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: filesize
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -202,13 +202,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("RAM required")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: ramrequired + qsTr(" GB")
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -224,13 +224,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Parameters")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: parameters
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -246,13 +246,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Quant")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: quant
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}
@ -268,13 +268,13 @@ Rectangle {
Layout.rightMargin: 20
Text {
text: qsTr("Type")
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
color: theme.mutedDarkTextColor
}
Text {
text: type
color: theme.textColor
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeSmall
font.bold: true
}
}

View File

@ -20,7 +20,7 @@ ColumnLayout {
Label {
id: mainTextLabel
color: theme.settingsTitleTextColor
font.pixelSize: theme.fontSizeSmall
font.pixelSize: theme.fontSizeLarger
font.bold: true
onLinkActivated: function(link) {
root.linkActivated(link);
@ -28,12 +28,13 @@ ColumnLayout {
}
Label {
id: helpTextLabel
visible: text !== ""
Layout.fillWidth: true
wrapMode: Text.Wrap
color: theme.settingsTitleTextColor
text: mainTextLabel.text
font.pixelSize: theme.fontSizeSmaller
font.pixelSize: theme.fontSizeLarge
font.bold: false
onLinkActivated: function(link) {
root.linkActivated(link);
}

View File

@ -0,0 +1,19 @@
import QtQuick
import QtQuick.Controls
Text {
id: text
signal click()
property string tooltip
HoverHandler { id: hoverHandler }
TapHandler { onTapped: { click() } }
font.bold: true
font.underline: hoverHandler.hovered
font.pixelSize: theme.fontSizeSmall
ToolTip.text: tooltip
ToolTip.visible: tooltip !== "" && hoverHandler.hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
}

View File

@ -33,7 +33,7 @@ Button {
visible: myButton.toggled
border.color: myButton.toggledColor
border.width: myButton.toggledWidth
radius: 10
radius: 8
}
Image {
id: image

View File

@ -1058,19 +1058,17 @@ QtObject {
}
}
property real fontSizeLargeCapped: MySettings.fontSize === "Small" ? 12 : 17
property real fontScale: MySettings.fontSize === "Small" ? 1 :
MySettings.fontSize === "Medium" ? 1.3 :
/* "Large" */ 1.8
property real fontSizeLarge: MySettings.fontSize === "Small" ? 12 :
MySettings.fontSize === "Medium" ? 17 :
22
property real fontSizeLargest: MySettings.fontSize === "Small" ? 19 :
MySettings.fontSize === "Medium" ? 24 :
26
property real fontSizeSmaller: fontSizeLarge - 4
property real fontSizeSmall: fontSizeLarge - 2
property real fontSizeLarger: fontSizeLarge + 2
property real fontSizeBannerSmall: fontSizeLargest + 10
property real fontSizeBanner: fontSizeLargest + 40
property real fontSizeSmallest: 8 * fontScale
property real fontSizeSmaller: 9 * fontScale
property real fontSizeSmall: 10 * fontScale
property real fontSizeMedium: 11 * fontScale
property real fontSizeLarge: 12 * fontScale
property real fontSizeLarger: 14 * fontScale
property real fontSizeLargest: 18 * fontScale
property real fontSizeBannerSmall: 24 * fontScale**.8
property real fontSizeBanner: 48 * fontScale**.8
}