mirror of
https://github.com/nomic-ai/gpt4all
synced 2024-11-10 01:10:35 +00:00
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:
parent
426aa5eb47
commit
2c8d634b5b
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ Rectangle {
|
||||
bottomPadding: 5
|
||||
text: parent.section
|
||||
color: theme.chatDrawerSectionHeader
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmallest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 1530
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 20
|
||||
spacing: 30
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -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 {
|
||||
|
@ -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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
19
gpt4all-chat/qml/MyTextButton.qml
Normal file
19
gpt4all-chat/qml/MyTextButton.qml
Normal 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
|
||||
}
|
@ -33,7 +33,7 @@ Button {
|
||||
visible: myButton.toggled
|
||||
border.color: myButton.toggledColor
|
||||
border.width: myButton.toggledWidth
|
||||
radius: 10
|
||||
radius: 8
|
||||
}
|
||||
Image {
|
||||
id: image
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user