mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2024-10-01 01:06:10 -04: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
|
main.qml
|
||||||
qml/AddCollectionView.qml
|
qml/AddCollectionView.qml
|
||||||
qml/AddModelView.qml
|
qml/AddModelView.qml
|
||||||
|
qml/ApplicationSettings.qml
|
||||||
qml/ChatDrawer.qml
|
qml/ChatDrawer.qml
|
||||||
qml/ChatView.qml
|
qml/ChatView.qml
|
||||||
qml/CollectionsDrawer.qml
|
qml/CollectionsDrawer.qml
|
||||||
qml/HomeView.qml
|
qml/HomeView.qml
|
||||||
|
qml/LocalDocsSettings.qml
|
||||||
|
qml/LocalDocsView.qml
|
||||||
|
qml/ModelSettings.qml
|
||||||
qml/ModelsView.qml
|
qml/ModelsView.qml
|
||||||
qml/NetworkDialog.qml
|
qml/NetworkDialog.qml
|
||||||
qml/NewVersionDialog.qml
|
qml/NewVersionDialog.qml
|
||||||
qml/ThumbsDownDialog.qml
|
qml/PopupDialog.qml
|
||||||
qml/SettingsView.qml
|
qml/SettingsView.qml
|
||||||
qml/StartupDialog.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/SwitchModelDialog.qml
|
||||||
qml/MySettingsTab.qml
|
qml/Theme.qml
|
||||||
qml/MySettingsStack.qml
|
qml/ThumbsDownDialog.qml
|
||||||
qml/MySettingsDestructiveButton.qml
|
qml/MyBusyIndicator.qml
|
||||||
qml/MySettingsButton.qml
|
|
||||||
qml/MySettingsLabel.qml
|
|
||||||
qml/MySlug.qml
|
|
||||||
qml/MyButton.qml
|
qml/MyButton.qml
|
||||||
|
qml/MyCheckBox.qml
|
||||||
qml/MyComboBox.qml
|
qml/MyComboBox.qml
|
||||||
qml/MyDialog.qml
|
qml/MyDialog.qml
|
||||||
qml/MyDirectoryField.qml
|
qml/MyDirectoryField.qml
|
||||||
qml/MyFancyLink.qml
|
qml/MyFancyLink.qml
|
||||||
qml/MyTextArea.qml
|
|
||||||
qml/MyTextField.qml
|
|
||||||
qml/MyCheckBox.qml
|
|
||||||
qml/MyBusyIndicator.qml
|
|
||||||
qml/MyMiniButton.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/MyToolButton.qml
|
||||||
qml/MyWelcomeButton.qml
|
qml/MyWelcomeButton.qml
|
||||||
RESOURCES
|
RESOURCES
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVariantMap>
|
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include <Qt>
|
#include <Qt>
|
||||||
#include <QtLogging>
|
#include <QtLogging>
|
||||||
@ -340,181 +339,8 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
|||||||
model->setRequestURL(modelInfo.url());
|
model->setRequestURL(modelInfo.url());
|
||||||
model->setAPIKey(apiKey);
|
model->setAPIKey(apiKey);
|
||||||
m_llModelInfo.resetModel(this, model);
|
m_llModelInfo.resetModel(this, model);
|
||||||
} else {
|
} else if (!loadNewModel(modelInfo, modelLoadProps)) {
|
||||||
QElapsedTimer modelLoadTimer;
|
return false; // m_shouldBeLoaded became false
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#if defined(DEBUG_MODEL_LOADING)
|
#if defined(DEBUG_MODEL_LOADING)
|
||||||
qDebug() << "new model" << m_llmThread.objectName() << m_llModelInfo.model.get();
|
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);
|
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
|
bool ChatLLM::isModelLoaded() const
|
||||||
{
|
{
|
||||||
return m_llModelInfo.model && m_llModelInfo.model->isModelLoaded();
|
return m_llModelInfo.model && m_llModelInfo.model->isModelLoaded();
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QVariantMap>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
@ -214,6 +215,8 @@ protected:
|
|||||||
quint32 m_promptResponseTokens;
|
quint32 m_promptResponseTokens;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool loadNewModel(const ModelInfo &modelInfo, QVariantMap &modelLoadProps);
|
||||||
|
|
||||||
std::string m_response;
|
std::string m_response;
|
||||||
std::string m_nameResponse;
|
std::string m_nameResponse;
|
||||||
LLModelInfo m_llModelInfo;
|
LLModelInfo m_llModelInfo;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace Qt::Literals::StringLiterals;
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
|
||||||
@ -63,9 +64,13 @@ void EmbeddingLLMWorker::wait()
|
|||||||
|
|
||||||
bool EmbeddingLLMWorker::loadModel()
|
bool EmbeddingLLMWorker::loadModel()
|
||||||
{
|
{
|
||||||
|
constexpr int n_ctx = 2048;
|
||||||
|
|
||||||
m_nomicAPIKey.clear();
|
m_nomicAPIKey.clear();
|
||||||
m_model = nullptr;
|
m_model = nullptr;
|
||||||
|
|
||||||
|
// TODO(jared): react to setting changes without restarting
|
||||||
|
|
||||||
if (MySettings::globalInstance()->localDocsUseRemoteEmbed()) {
|
if (MySettings::globalInstance()->localDocsUseRemoteEmbed()) {
|
||||||
m_nomicAPIKey = MySettings::globalInstance()->localDocsNomicAPIKey();
|
m_nomicAPIKey = MySettings::globalInstance()->localDocsNomicAPIKey();
|
||||||
return true;
|
return true;
|
||||||
@ -79,29 +84,86 @@ bool EmbeddingLLMWorker::loadModel()
|
|||||||
|
|
||||||
QString filePath = embPathFmt.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL);
|
QString filePath = embPathFmt.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL);
|
||||||
if (!QFileInfo::exists(filePath)) {
|
if (!QFileInfo::exists(filePath)) {
|
||||||
qWarning() << "WARNING: Local embedding model not found";
|
qWarning() << "embllm WARNING: Local embedding model not found";
|
||||||
return false;
|
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 {
|
try {
|
||||||
m_model = LLModel::Implementation::construct(filePath.toStdString());
|
m_model = LLModel::Implementation::construct(filePath.toStdString(), backend, n_ctx);
|
||||||
} catch (const std::exception &e) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: explicitly loads model on CPU to avoid GPU OOM
|
bool actualDeviceIsCPU = true;
|
||||||
// TODO(cebtenzzre): support GPU-accelerated embeddings
|
|
||||||
bool success = m_model->loadModel(filePath.toStdString(), 2048, 0);
|
#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) {
|
if (!success) {
|
||||||
qWarning() << "WARNING: Could not load embedding model";
|
qWarning() << "embllm WARNING: Could not load embedding model";
|
||||||
delete m_model;
|
delete m_model;
|
||||||
m_model = nullptr;
|
m_model = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_model->supportsEmbedding()) {
|
if (!m_model->supportsEmbedding()) {
|
||||||
qWarning() << "WARNING: Model type does not support embeddings";
|
qWarning() << "embllm WARNING: Model type does not support embeddings";
|
||||||
delete m_model;
|
delete m_model;
|
||||||
m_model = nullptr;
|
m_model = nullptr;
|
||||||
return false;
|
return false;
|
||||||
@ -128,7 +190,7 @@ std::vector<float> EmbeddingLLMWorker::generateQueryEmbedding(const QString &tex
|
|||||||
std::vector<float> embedding(m_model->embeddingSize());
|
std::vector<float> embedding(m_model->embeddingSize());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_model->embed({text.toStdString()}, embedding.data(), true);
|
m_model->embed({text.toStdString()}, embedding.data(), /*isRetrieval*/ true);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
|
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
|
||||||
return {};
|
return {};
|
||||||
@ -203,26 +265,34 @@ void EmbeddingLLMWorker::docEmbeddingsRequested(const QVector<EmbeddingChunk> &c
|
|||||||
if (!isNomic) {
|
if (!isNomic) {
|
||||||
QVector<EmbeddingResult> results;
|
QVector<EmbeddingResult> results;
|
||||||
results.reserve(chunks.size());
|
results.reserve(chunks.size());
|
||||||
|
std::vector<std::string> texts;
|
||||||
|
texts.reserve(chunks.size());
|
||||||
for (const auto &c: chunks) {
|
for (const auto &c: chunks) {
|
||||||
EmbeddingResult result;
|
EmbeddingResult result;
|
||||||
result.model = c.model;
|
result.model = c.model;
|
||||||
result.folder_id = c.folder_id;
|
result.folder_id = c.folder_id;
|
||||||
result.chunk_id = c.chunk_id;
|
result.chunk_id = c.chunk_id;
|
||||||
// TODO(cebtenzzre): take advantage of batched embeddings
|
|
||||||
result.embedding.resize(m_model->embeddingSize());
|
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;
|
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);
|
emit embeddingsGenerated(results);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -204,7 +204,7 @@ Window {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
width: MySettings.fontSize === "Small" ? 86 : 100
|
width: 16 + 52 * theme.fontScale
|
||||||
color: theme.viewBarBackground
|
color: theme.viewBarBackground
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@ -213,20 +213,20 @@ Window {
|
|||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
Layout.margins: 0
|
Layout.margins: 0
|
||||||
spacing: 18
|
spacing: 16
|
||||||
|
|
||||||
MyToolButton {
|
MyToolButton {
|
||||||
id: homeButton
|
id: homeButton
|
||||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
Layout.preferredHeight: 48
|
Layout.preferredHeight: 38 * theme.fontScale
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
toggledWidth: 0
|
toggledWidth: 0
|
||||||
toggled: homeView.isShown()
|
toggled: homeView.isShown()
|
||||||
toggledColor: theme.iconBackgroundViewBarToggled
|
toggledColor: theme.iconBackgroundViewBarToggled
|
||||||
imageWidth: 34
|
imageWidth: 25 * theme.fontScale
|
||||||
imageHeight: 34
|
imageHeight: 25 * theme.fontScale
|
||||||
source: "qrc:/gpt4all/icons/home.svg"
|
source: "qrc:/gpt4all/icons/home.svg"
|
||||||
Accessible.name: qsTr("Home view")
|
Accessible.name: qsTr("Home view")
|
||||||
Accessible.description: qsTr("Home view of application")
|
Accessible.description: qsTr("Home view of application")
|
||||||
@ -238,10 +238,10 @@ Window {
|
|||||||
Text {
|
Text {
|
||||||
Layout.topMargin: -20
|
Layout.topMargin: -20
|
||||||
text: qsTr("Home")
|
text: qsTr("Home")
|
||||||
font.pixelSize: theme.fontSizeLargeCapped
|
font.pixelSize: theme.fontSizeMedium
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: homeButton.hovered ? homeButton.backgroundColorHovered : homeButton.backgroundColor
|
color: homeButton.hovered ? homeButton.backgroundColorHovered : homeButton.backgroundColor
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: function(eventPoint, button) {
|
onTapped: function(eventPoint, button) {
|
||||||
@ -254,14 +254,14 @@ Window {
|
|||||||
id: chatButton
|
id: chatButton
|
||||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
Layout.preferredHeight: 48
|
Layout.preferredHeight: 38 * theme.fontScale
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
toggledWidth: 0
|
toggledWidth: 0
|
||||||
toggled: chatView.isShown()
|
toggled: chatView.isShown()
|
||||||
toggledColor: theme.iconBackgroundViewBarToggled
|
toggledColor: theme.iconBackgroundViewBarToggled
|
||||||
imageWidth: 34
|
imageWidth: 25 * theme.fontScale
|
||||||
imageHeight: 34
|
imageHeight: 25 * theme.fontScale
|
||||||
source: "qrc:/gpt4all/icons/chat.svg"
|
source: "qrc:/gpt4all/icons/chat.svg"
|
||||||
Accessible.name: qsTr("Chat view")
|
Accessible.name: qsTr("Chat view")
|
||||||
Accessible.description: qsTr("Chat view to interact with models")
|
Accessible.description: qsTr("Chat view to interact with models")
|
||||||
@ -273,10 +273,10 @@ Window {
|
|||||||
Text {
|
Text {
|
||||||
Layout.topMargin: -20
|
Layout.topMargin: -20
|
||||||
text: qsTr("Chats")
|
text: qsTr("Chats")
|
||||||
font.pixelSize: theme.fontSizeLargeCapped
|
font.pixelSize: theme.fontSizeMedium
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: chatButton.hovered ? chatButton.backgroundColorHovered : chatButton.backgroundColor
|
color: chatButton.hovered ? chatButton.backgroundColorHovered : chatButton.backgroundColor
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: function(eventPoint, button) {
|
onTapped: function(eventPoint, button) {
|
||||||
@ -289,13 +289,13 @@ Window {
|
|||||||
id: modelsButton
|
id: modelsButton
|
||||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
Layout.preferredHeight: 48
|
Layout.preferredHeight: 38 * theme.fontScale
|
||||||
toggledWidth: 0
|
toggledWidth: 0
|
||||||
toggled: modelsView.isShown()
|
toggled: modelsView.isShown()
|
||||||
toggledColor: theme.iconBackgroundViewBarToggled
|
toggledColor: theme.iconBackgroundViewBarToggled
|
||||||
imageWidth: 34
|
imageWidth: 25 * theme.fontScale
|
||||||
imageHeight: 34
|
imageHeight: 25 * theme.fontScale
|
||||||
source: "qrc:/gpt4all/icons/models.svg"
|
source: "qrc:/gpt4all/icons/models.svg"
|
||||||
Accessible.name: qsTr("Models")
|
Accessible.name: qsTr("Models")
|
||||||
Accessible.description: qsTr("Models view for installed models")
|
Accessible.description: qsTr("Models view for installed models")
|
||||||
@ -307,10 +307,10 @@ Window {
|
|||||||
Text {
|
Text {
|
||||||
Layout.topMargin: -20
|
Layout.topMargin: -20
|
||||||
text: qsTr("Models")
|
text: qsTr("Models")
|
||||||
font.pixelSize: theme.fontSizeLargeCapped
|
font.pixelSize: theme.fontSizeMedium
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: modelsButton.hovered ? modelsButton.backgroundColorHovered : modelsButton.backgroundColor
|
color: modelsButton.hovered ? modelsButton.backgroundColorHovered : modelsButton.backgroundColor
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: function(eventPoint, button) {
|
onTapped: function(eventPoint, button) {
|
||||||
@ -323,13 +323,13 @@ Window {
|
|||||||
id: localdocsButton
|
id: localdocsButton
|
||||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
Layout.preferredHeight: 48
|
Layout.preferredHeight: 38 * theme.fontScale
|
||||||
toggledWidth: 0
|
toggledWidth: 0
|
||||||
toggledColor: theme.iconBackgroundViewBarToggled
|
toggledColor: theme.iconBackgroundViewBarToggled
|
||||||
toggled: localDocsView.isShown()
|
toggled: localDocsView.isShown()
|
||||||
imageWidth: 34
|
imageWidth: 25 * theme.fontScale
|
||||||
imageHeight: 34
|
imageHeight: 25 * theme.fontScale
|
||||||
source: "qrc:/gpt4all/icons/db.svg"
|
source: "qrc:/gpt4all/icons/db.svg"
|
||||||
Accessible.name: qsTr("LocalDocs")
|
Accessible.name: qsTr("LocalDocs")
|
||||||
Accessible.description: qsTr("LocalDocs view to configure and use local docs")
|
Accessible.description: qsTr("LocalDocs view to configure and use local docs")
|
||||||
@ -341,10 +341,10 @@ Window {
|
|||||||
Text {
|
Text {
|
||||||
Layout.topMargin: -20
|
Layout.topMargin: -20
|
||||||
text: qsTr("LocalDocs")
|
text: qsTr("LocalDocs")
|
||||||
font.pixelSize: theme.fontSizeLargeCapped
|
font.pixelSize: theme.fontSizeMedium
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: localdocsButton.hovered ? localdocsButton.backgroundColorHovered : localdocsButton.backgroundColor
|
color: localdocsButton.hovered ? localdocsButton.backgroundColorHovered : localdocsButton.backgroundColor
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: function(eventPoint, button) {
|
onTapped: function(eventPoint, button) {
|
||||||
@ -357,13 +357,13 @@ Window {
|
|||||||
id: settingsButton
|
id: settingsButton
|
||||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
Layout.preferredHeight: 48
|
Layout.preferredHeight: 38 * theme.fontScale
|
||||||
toggledWidth: 0
|
toggledWidth: 0
|
||||||
toggledColor: theme.iconBackgroundViewBarToggled
|
toggledColor: theme.iconBackgroundViewBarToggled
|
||||||
toggled: settingsView.isShown()
|
toggled: settingsView.isShown()
|
||||||
imageWidth: 34
|
imageWidth: 25 * theme.fontScale
|
||||||
imageHeight: 34
|
imageHeight: 25 * theme.fontScale
|
||||||
source: "qrc:/gpt4all/icons/settings.svg"
|
source: "qrc:/gpt4all/icons/settings.svg"
|
||||||
Accessible.name: qsTr("Settings")
|
Accessible.name: qsTr("Settings")
|
||||||
Accessible.description: qsTr("Settings view for application configuration")
|
Accessible.description: qsTr("Settings view for application configuration")
|
||||||
@ -375,10 +375,10 @@ Window {
|
|||||||
Text {
|
Text {
|
||||||
Layout.topMargin: -20
|
Layout.topMargin: -20
|
||||||
text: qsTr("Settings")
|
text: qsTr("Settings")
|
||||||
font.pixelSize: theme.fontSizeLargeCapped
|
font.pixelSize: theme.fontSizeMedium
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: settingsButton.hovered ? settingsButton.backgroundColorHovered : settingsButton.backgroundColor
|
color: settingsButton.hovered ? settingsButton.backgroundColorHovered : settingsButton.backgroundColor
|
||||||
Layout.preferredWidth: 48
|
Layout.preferredWidth: 38 * theme.fontScale
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: function(eventPoint, button) {
|
onTapped: function(eventPoint, button) {
|
||||||
|
@ -47,6 +47,7 @@ static const QVariantMap basicDefaults {
|
|||||||
{ "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } },
|
{ "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } },
|
||||||
{ "localdocs/useRemoteEmbed", false },
|
{ "localdocs/useRemoteEmbed", false },
|
||||||
{ "localdocs/nomicAPIKey", "" },
|
{ "localdocs/nomicAPIKey", "" },
|
||||||
|
{ "localdocs/embedDevice", "Auto" },
|
||||||
{ "network/attribution", "" },
|
{ "network/attribution", "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,6 +78,22 @@ static QString defaultLocalModelsPath()
|
|||||||
return canonicalLocalPath;
|
return canonicalLocalPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList getDevices(bool skipKompute = false)
|
||||||
|
{
|
||||||
|
QStringList deviceList { "Auto" };
|
||||||
|
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
||||||
|
deviceList << "Metal";
|
||||||
|
#else
|
||||||
|
std::vector<LLModel::GPUDevice> devices = LLModel::Implementation::availableGPUDevices();
|
||||||
|
for (LLModel::GPUDevice &d : devices) {
|
||||||
|
if (!skipKompute || strcmp(d.backend, "kompute"))
|
||||||
|
deviceList << QString::fromStdString(d.selectionName());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
deviceList << "CPU";
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
class MyPrivateSettings: public MySettings { };
|
class MyPrivateSettings: public MySettings { };
|
||||||
Q_GLOBAL_STATIC(MyPrivateSettings, settingsInstance)
|
Q_GLOBAL_STATIC(MyPrivateSettings, settingsInstance)
|
||||||
MySettings *MySettings::globalInstance()
|
MySettings *MySettings::globalInstance()
|
||||||
@ -85,18 +102,10 @@ MySettings *MySettings::globalInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MySettings::MySettings()
|
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
|
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());
|
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)
|
void MySettings::restoreModelDefaults(const ModelInfo &info)
|
||||||
{
|
{
|
||||||
setModelTemperature(info, info.m_temperature);
|
setModelTemperature(info, info.m_temperature);
|
||||||
@ -162,6 +160,7 @@ void MySettings::restoreLocalDocsDefaults()
|
|||||||
setLocalDocsFileExtensions(basicDefaults.value("localdocs/fileExtensions").toStringList());
|
setLocalDocsFileExtensions(basicDefaults.value("localdocs/fileExtensions").toStringList());
|
||||||
setLocalDocsUseRemoteEmbed(basicDefaults.value("localdocs/useRemoteEmbed").toBool());
|
setLocalDocsUseRemoteEmbed(basicDefaults.value("localdocs/useRemoteEmbed").toBool());
|
||||||
setLocalDocsNomicAPIKey(basicDefaults.value("localdocs/nomicAPIKey").toString());
|
setLocalDocsNomicAPIKey(basicDefaults.value("localdocs/nomicAPIKey").toString());
|
||||||
|
setLocalDocsEmbedDevice(basicDefaults.value("localdocs/embedDevice").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySettings::eraseModel(const ModelInfo &info)
|
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(); }
|
QStringList MySettings::localDocsFileExtensions() const { return getBasicSetting("localdocs/fileExtensions").toStringList(); }
|
||||||
bool MySettings::localDocsUseRemoteEmbed() const { return getBasicSetting("localdocs/useRemoteEmbed").toBool(); }
|
bool MySettings::localDocsUseRemoteEmbed() const { return getBasicSetting("localdocs/useRemoteEmbed").toBool(); }
|
||||||
QString MySettings::localDocsNomicAPIKey() const { return getBasicSetting("localdocs/nomicAPIKey" ).toString(); }
|
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(); }
|
QString MySettings::networkAttribution() const { return getBasicSetting("network/attribution" ).toString(); }
|
||||||
|
|
||||||
void MySettings::setSaveChatsContext(bool value) { setBasicSetting("saveChatsContext", value); }
|
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::setLocalDocsFileExtensions(const QStringList &value) { setBasicSetting("localdocs/fileExtensions", value, "localDocsFileExtensions"); }
|
||||||
void MySettings::setLocalDocsUseRemoteEmbed(bool value) { setBasicSetting("localdocs/useRemoteEmbed", value, "localDocsUseRemoteEmbed"); }
|
void MySettings::setLocalDocsUseRemoteEmbed(bool value) { setBasicSetting("localdocs/useRemoteEmbed", value, "localDocsUseRemoteEmbed"); }
|
||||||
void MySettings::setLocalDocsNomicAPIKey(const QString &value) { setBasicSetting("localdocs/nomicAPIKey", value, "localDocsNomicAPIKey"); }
|
void MySettings::setLocalDocsNomicAPIKey(const QString &value) { setBasicSetting("localdocs/nomicAPIKey", value, "localDocsNomicAPIKey"); }
|
||||||
|
void MySettings::setLocalDocsEmbedDevice(const QString &value) { setBasicSetting("localdocs/embedDevice", value, "localDocsEmbedDevice"); }
|
||||||
void MySettings::setNetworkAttribution(const QString &value) { setBasicSetting("network/attribution", value, "networkAttribution"); }
|
void MySettings::setNetworkAttribution(const QString &value) { setBasicSetting("network/attribution", value, "networkAttribution"); }
|
||||||
|
|
||||||
QString MySettings::modelPath()
|
QString MySettings::modelPath()
|
||||||
@ -446,11 +447,10 @@ QString MySettings::device()
|
|||||||
|
|
||||||
void MySettings::setDevice(const QString &value)
|
void MySettings::setDevice(const QString &value)
|
||||||
{
|
{
|
||||||
if (device() == value)
|
if (device() != value) {
|
||||||
return;
|
m_settings.setValue("device", value);
|
||||||
|
emit deviceChanged();
|
||||||
m_settings.setValue("device", value);
|
}
|
||||||
emit deviceChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySettings::forceMetal() const
|
bool MySettings::forceMetal() const
|
||||||
@ -460,10 +460,10 @@ bool MySettings::forceMetal() const
|
|||||||
|
|
||||||
void MySettings::setForceMetal(bool value)
|
void MySettings::setForceMetal(bool value)
|
||||||
{
|
{
|
||||||
if (m_forceMetal == value)
|
if (m_forceMetal != value) {
|
||||||
return;
|
m_forceMetal = value;
|
||||||
m_forceMetal = value;
|
emit forceMetalChanged(value);
|
||||||
emit forceMetalChanged(value);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySettings::networkIsActive() const
|
bool MySettings::networkIsActive() const
|
||||||
|
@ -31,11 +31,13 @@ class MySettings : public QObject
|
|||||||
Q_PROPERTY(QStringList localDocsFileExtensions READ localDocsFileExtensions WRITE setLocalDocsFileExtensions NOTIFY localDocsFileExtensionsChanged)
|
Q_PROPERTY(QStringList localDocsFileExtensions READ localDocsFileExtensions WRITE setLocalDocsFileExtensions NOTIFY localDocsFileExtensionsChanged)
|
||||||
Q_PROPERTY(bool localDocsUseRemoteEmbed READ localDocsUseRemoteEmbed WRITE setLocalDocsUseRemoteEmbed NOTIFY localDocsUseRemoteEmbedChanged)
|
Q_PROPERTY(bool localDocsUseRemoteEmbed READ localDocsUseRemoteEmbed WRITE setLocalDocsUseRemoteEmbed NOTIFY localDocsUseRemoteEmbedChanged)
|
||||||
Q_PROPERTY(QString localDocsNomicAPIKey READ localDocsNomicAPIKey WRITE setLocalDocsNomicAPIKey NOTIFY localDocsNomicAPIKeyChanged)
|
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(QString networkAttribution READ networkAttribution WRITE setNetworkAttribution NOTIFY networkAttributionChanged)
|
||||||
Q_PROPERTY(bool networkIsActive READ networkIsActive WRITE setNetworkIsActive NOTIFY networkIsActiveChanged)
|
Q_PROPERTY(bool networkIsActive READ networkIsActive WRITE setNetworkIsActive NOTIFY networkIsActiveChanged)
|
||||||
Q_PROPERTY(bool networkUsageStatsActive READ networkUsageStatsActive WRITE setNetworkUsageStatsActive NOTIFY networkUsageStatsActiveChanged)
|
Q_PROPERTY(bool networkUsageStatsActive READ networkUsageStatsActive WRITE setNetworkUsageStatsActive NOTIFY networkUsageStatsActiveChanged)
|
||||||
Q_PROPERTY(QString device READ device WRITE setDevice NOTIFY deviceChanged)
|
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)
|
Q_PROPERTY(int networkPort READ networkPort WRITE setNetworkPort NOTIFY networkPortChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -138,6 +140,8 @@ public:
|
|||||||
void setLocalDocsUseRemoteEmbed(bool value);
|
void setLocalDocsUseRemoteEmbed(bool value);
|
||||||
QString localDocsNomicAPIKey() const;
|
QString localDocsNomicAPIKey() const;
|
||||||
void setLocalDocsNomicAPIKey(const QString &value);
|
void setLocalDocsNomicAPIKey(const QString &value);
|
||||||
|
QString localDocsEmbedDevice() const;
|
||||||
|
void setLocalDocsEmbedDevice(const QString &value);
|
||||||
|
|
||||||
// Network settings
|
// Network settings
|
||||||
QString networkAttribution() const;
|
QString networkAttribution() const;
|
||||||
@ -151,9 +155,6 @@ public:
|
|||||||
int networkPort() const;
|
int networkPort() const;
|
||||||
void setNetworkPort(int value);
|
void setNetworkPort(int value);
|
||||||
|
|
||||||
QVector<QString> deviceList() const;
|
|
||||||
void setDeviceList(const QVector<QString> &value);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void nameChanged(const ModelInfo &info);
|
void nameChanged(const ModelInfo &info);
|
||||||
void filenameChanged(const ModelInfo &info);
|
void filenameChanged(const ModelInfo &info);
|
||||||
@ -185,18 +186,19 @@ Q_SIGNALS:
|
|||||||
void localDocsFileExtensionsChanged();
|
void localDocsFileExtensionsChanged();
|
||||||
void localDocsUseRemoteEmbedChanged();
|
void localDocsUseRemoteEmbedChanged();
|
||||||
void localDocsNomicAPIKeyChanged();
|
void localDocsNomicAPIKeyChanged();
|
||||||
|
void localDocsEmbedDeviceChanged();
|
||||||
void networkAttributionChanged();
|
void networkAttributionChanged();
|
||||||
void networkIsActiveChanged();
|
void networkIsActiveChanged();
|
||||||
void networkPortChanged();
|
void networkPortChanged();
|
||||||
void networkUsageStatsActiveChanged();
|
void networkUsageStatsActiveChanged();
|
||||||
void attemptModelLoadChanged();
|
void attemptModelLoadChanged();
|
||||||
void deviceChanged();
|
void deviceChanged();
|
||||||
void deviceListChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSettings m_settings;
|
QSettings m_settings;
|
||||||
bool m_forceMetal;
|
bool m_forceMetal;
|
||||||
QVector<QString> m_deviceList;
|
const QStringList m_deviceList;
|
||||||
|
const QStringList m_embeddingsDeviceList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit MySettings();
|
explicit MySettings();
|
||||||
|
@ -603,13 +603,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("File size")
|
text: qsTr("File size")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: filesize
|
text: filesize
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,13 +625,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("RAM required")
|
text: qsTr("RAM required")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
|
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -647,13 +647,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Parameters")
|
text: qsTr("Parameters")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: parameters !== "" ? parameters : "?"
|
text: parameters !== "" ? parameters : "?"
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,13 +669,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Quant")
|
text: qsTr("Quant")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: quant
|
text: quant
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -691,13 +691,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Type")
|
text: qsTr("Type")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: type
|
text: type
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,19 @@ MySettingsTab {
|
|||||||
rowSpacing: 30
|
rowSpacing: 30
|
||||||
columnSpacing: 10
|
columnSpacing: 10
|
||||||
|
|
||||||
ColumnLayout {
|
Label {
|
||||||
Layout.row: 0
|
Layout.row: 0
|
||||||
Layout.column: 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.columnSpan: 3
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: 10
|
spacing: 10
|
||||||
@ -72,7 +82,7 @@ MySettingsTab {
|
|||||||
color: theme.styledTextColor
|
color: theme.styledTextColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
font.bold: true
|
font.bold: true
|
||||||
text: "General"
|
text: qsTr("General")
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@ -85,22 +95,21 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: themeLabel
|
id: themeLabel
|
||||||
text: qsTr("Theme")
|
text: qsTr("Theme")
|
||||||
helpText: qsTr("Customize the colors of GPT4All")
|
helpText: qsTr("The application color scheme.")
|
||||||
Layout.row: 1
|
Layout.row: 2
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyComboBox {
|
MyComboBox {
|
||||||
id: themeBox
|
id: themeBox
|
||||||
Layout.row: 1
|
Layout.row: 2
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 200
|
Layout.minimumWidth: 200
|
||||||
Layout.maximumWidth: 200
|
Layout.maximumWidth: 200
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
model: [qsTr("Dark"), qsTr("Light"), qsTr("LegacyDark")]
|
model: [qsTr("Dark"), qsTr("Light"), qsTr("LegacyDark")]
|
||||||
Accessible.role: Accessible.ComboBox
|
Accessible.name: themeLabel.text
|
||||||
Accessible.name: qsTr("Color theme")
|
Accessible.description: themeLabel.helpText
|
||||||
Accessible.description: qsTr("Color theme for the chat client to use")
|
|
||||||
function updateModel() {
|
function updateModel() {
|
||||||
themeBox.currentIndex = themeBox.indexOfValue(MySettings.chatTheme);
|
themeBox.currentIndex = themeBox.indexOfValue(MySettings.chatTheme);
|
||||||
}
|
}
|
||||||
@ -120,22 +129,21 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: fontLabel
|
id: fontLabel
|
||||||
text: qsTr("Font Size")
|
text: qsTr("Font Size")
|
||||||
helpText: qsTr("How big your font is displayed")
|
helpText: qsTr("The size of text in the application.")
|
||||||
Layout.row: 2
|
Layout.row: 3
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyComboBox {
|
MyComboBox {
|
||||||
id: fontBox
|
id: fontBox
|
||||||
Layout.row: 2
|
Layout.row: 3
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 200
|
Layout.minimumWidth: 200
|
||||||
Layout.maximumWidth: 200
|
Layout.maximumWidth: 200
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
model: ["Small", "Medium", "Large"]
|
model: ["Small", "Medium", "Large"]
|
||||||
Accessible.role: Accessible.ComboBox
|
Accessible.name: fontLabel.text
|
||||||
Accessible.name: qsTr("Font size")
|
Accessible.description: fontLabel.helpText
|
||||||
Accessible.description: qsTr("Font size of the chat client")
|
|
||||||
function updateModel() {
|
function updateModel() {
|
||||||
fontBox.currentIndex = fontBox.indexOfValue(MySettings.fontSize);
|
fontBox.currentIndex = fontBox.indexOfValue(MySettings.fontSize);
|
||||||
}
|
}
|
||||||
@ -155,59 +163,54 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: deviceLabel
|
id: deviceLabel
|
||||||
text: qsTr("Device")
|
text: qsTr("Device")
|
||||||
helpText: qsTr("The hardware device used to load the model")
|
helpText: qsTr('The compute device used for text generation. "Auto" uses Vulkan or Metal.')
|
||||||
Layout.row: 3
|
Layout.row: 4
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyComboBox {
|
MyComboBox {
|
||||||
id: deviceBox
|
id: deviceBox
|
||||||
Layout.row: 3
|
Layout.row: 4
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 400
|
Layout.minimumWidth: 400
|
||||||
Layout.maximumWidth: 400
|
Layout.maximumWidth: 400
|
||||||
Layout.fillWidth: false
|
Layout.fillWidth: false
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
model: MySettings.deviceList
|
model: MySettings.deviceList
|
||||||
Accessible.role: Accessible.ComboBox
|
Accessible.name: deviceLabel.text
|
||||||
Accessible.name: qsTr("Device")
|
Accessible.description: deviceLabel.helpText
|
||||||
Accessible.description: qsTr("Device of the chat client")
|
|
||||||
function updateModel() {
|
function updateModel() {
|
||||||
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device);
|
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device);
|
||||||
}
|
}
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
deviceBox.updateModel()
|
deviceBox.updateModel();
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: MySettings
|
target: MySettings
|
||||||
function onDeviceChanged() {
|
function onDeviceChanged() {
|
||||||
deviceBox.updateModel()
|
deviceBox.updateModel();
|
||||||
}
|
|
||||||
function onDeviceListChanged() {
|
|
||||||
deviceBox.updateModel()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onActivated: {
|
onActivated: {
|
||||||
MySettings.device = deviceBox.currentText
|
MySettings.device = deviceBox.currentText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: defaultModelLabel
|
id: defaultModelLabel
|
||||||
text: qsTr("Default model")
|
text: qsTr("Default Model")
|
||||||
helpText: qsTr("The preferred default model")
|
helpText: qsTr("The preferred model for new chats. Also used as the local server fallback.")
|
||||||
Layout.row: 4
|
Layout.row: 5
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyComboBox {
|
MyComboBox {
|
||||||
id: comboBox
|
id: comboBox
|
||||||
Layout.row: 4
|
Layout.row: 5
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 400
|
Layout.minimumWidth: 400
|
||||||
Layout.maximumWidth: 400
|
Layout.maximumWidth: 400
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
model: ModelList.userDefaultModelList
|
model: ModelList.userDefaultModelList
|
||||||
Accessible.role: Accessible.ComboBox
|
Accessible.name: defaultModelLabel.text
|
||||||
Accessible.name: qsTr("Default model")
|
Accessible.description: defaultModelLabel.helpText
|
||||||
Accessible.description: qsTr("Default model to use; the first item is the current default model")
|
|
||||||
function updateModel() {
|
function updateModel() {
|
||||||
comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel);
|
comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel);
|
||||||
}
|
}
|
||||||
@ -226,14 +229,14 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: modelPathLabel
|
id: modelPathLabel
|
||||||
text: qsTr("Download path")
|
text: qsTr("Download Path")
|
||||||
helpText: qsTr("The download folder for models")
|
helpText: qsTr("Where to store local models and the LocalDocs database.")
|
||||||
Layout.row: 5
|
Layout.row: 6
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.row: 5
|
Layout.row: 6
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
Layout.minimumWidth: 400
|
Layout.minimumWidth: 400
|
||||||
@ -245,11 +248,8 @@ MySettingsTab {
|
|||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
implicitWidth: 300
|
implicitWidth: 300
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
ToolTip.text: qsTr("Path where model files will be downloaded to")
|
Accessible.name: modelPathLabel.text
|
||||||
ToolTip.visible: hovered
|
Accessible.description: modelPathLabel.helpText
|
||||||
Accessible.role: Accessible.ToolTip
|
|
||||||
Accessible.name: modelPathDisplayField.text
|
|
||||||
Accessible.description: ToolTip.text
|
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
MySettings.modelPath = modelPathDisplayField.text
|
MySettings.modelPath = modelPathDisplayField.text
|
||||||
@ -271,29 +271,32 @@ MySettingsTab {
|
|||||||
|
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: dataLakeLabel
|
id: dataLakeLabel
|
||||||
text: qsTr("Opensource Datalake")
|
text: qsTr("Enable Datalake")
|
||||||
helpText: qsTr("Send your data to the GPT4All Open Source Datalake.")
|
helpText: qsTr("Send chats and feedback to the GPT4All Open-Source Datalake.")
|
||||||
Layout.row: 6
|
Layout.row: 7
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: dataLakeBox
|
id: dataLakeBox
|
||||||
Layout.row: 6
|
Layout.row: 7
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
checked: MySettings.networkIsActive
|
Component.onCompleted: { dataLakeBox.checked = MySettings.networkIsActive; }
|
||||||
onClicked: {
|
Connections {
|
||||||
if (MySettings.networkIsActive) {
|
target: MySettings
|
||||||
MySettings.networkIsActive = false
|
function onNetworkIsActiveChanged() { dataLakeBox.checked = MySettings.networkIsActive; }
|
||||||
} else
|
}
|
||||||
networkDialog.open()
|
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 {
|
ColumnLayout {
|
||||||
Layout.row: 7
|
Layout.row: 8
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
Layout.columnSpan: 3
|
Layout.columnSpan: 3
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -302,7 +305,7 @@ MySettingsTab {
|
|||||||
color: theme.styledTextColor
|
color: theme.styledTextColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
font.bold: true
|
font.bold: true
|
||||||
text: "Advanced"
|
text: qsTr("Advanced")
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@ -315,18 +318,16 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: nThreadsLabel
|
id: nThreadsLabel
|
||||||
text: qsTr("CPU Threads")
|
text: qsTr("CPU Threads")
|
||||||
helpText: qsTr("Number of CPU threads for inference and embedding")
|
helpText: qsTr("The number of CPU threads used for inference and embedding.")
|
||||||
Layout.row: 8
|
Layout.row: 9
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyTextField {
|
MyTextField {
|
||||||
text: MySettings.threadCount
|
text: MySettings.threadCount
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
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.alignment: Qt.AlignRight
|
||||||
Layout.row: 8
|
Layout.row: 9
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 200
|
Layout.minimumWidth: 200
|
||||||
Layout.maximumWidth: 200
|
Layout.maximumWidth: 200
|
||||||
@ -348,47 +349,43 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: saveChatsContextLabel
|
id: saveChatsContextLabel
|
||||||
text: qsTr("Save chat context")
|
text: qsTr("Save Chat Context")
|
||||||
helpText: qsTr("Save chat context to disk")
|
helpText: qsTr("Save the chat model's state to disk for faster loading. WARNING: Uses ~2GB per chat.")
|
||||||
Layout.row: 9
|
Layout.row: 10
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: saveChatsContextBox
|
id: saveChatsContextBox
|
||||||
Layout.row: 9
|
Layout.row: 10
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
checked: MySettings.saveChatsContext
|
checked: MySettings.saveChatsContext
|
||||||
onClicked: {
|
onClicked: {
|
||||||
MySettings.saveChatsContext = !MySettings.saveChatsContext
|
MySettings.saveChatsContext = !MySettings.saveChatsContext
|
||||||
}
|
}
|
||||||
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: serverChatLabel
|
id: serverChatLabel
|
||||||
text: qsTr("Enable API server")
|
text: qsTr("Enable Local Server")
|
||||||
helpText: qsTr("A local http server running on local port")
|
helpText: qsTr("Expose an OpenAI-Compatible server to localhost. WARNING: Results in increased resource usage.")
|
||||||
Layout.row: 10
|
Layout.row: 11
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: serverChatBox
|
id: serverChatBox
|
||||||
Layout.row: 10
|
Layout.row: 11
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
checked: MySettings.serverChat
|
checked: MySettings.serverChat
|
||||||
onClicked: {
|
onClicked: {
|
||||||
MySettings.serverChat = !MySettings.serverChat
|
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 {
|
MySettingsLabel {
|
||||||
id: serverPortLabel
|
id: serverPortLabel
|
||||||
text: qsTr("API Server Port:")
|
text: qsTr("API Server Port")
|
||||||
helpText: qsTr("A local port to run the server (Requires restart")
|
helpText: qsTr("The port to use for the local server. Requires restart.")
|
||||||
Layout.row: 11
|
Layout.row: 12
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
MyTextField {
|
MyTextField {
|
||||||
@ -396,9 +393,7 @@ MySettingsTab {
|
|||||||
text: MySettings.networkPort
|
text: MySettings.networkPort
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
ToolTip.text: qsTr("Api server port. WARNING: You need to restart the application for it to take effect")
|
Layout.row: 12
|
||||||
ToolTip.visible: hovered
|
|
||||||
Layout.row: 11
|
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
Layout.minimumWidth: 200
|
Layout.minimumWidth: 200
|
||||||
Layout.maximumWidth: 200
|
Layout.maximumWidth: 200
|
||||||
@ -416,8 +411,8 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Accessible.role: Accessible.EditableText
|
Accessible.role: Accessible.EditableText
|
||||||
Accessible.name: serverPortField.text
|
Accessible.name: serverPortLabel.text
|
||||||
Accessible.description: ToolTip.text
|
Accessible.description: serverPortLabel.helpText
|
||||||
}
|
}
|
||||||
|
|
||||||
/*MySettingsLabel {
|
/*MySettingsLabel {
|
||||||
@ -441,8 +436,8 @@ MySettingsTab {
|
|||||||
|
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: updatesLabel
|
id: updatesLabel
|
||||||
text: qsTr("Check for updates")
|
text: qsTr("Check For Updates")
|
||||||
helpText: qsTr("Click to see if an update to the application is available");
|
helpText: qsTr("Manually check for an update to GPT4All.");
|
||||||
Layout.row: 14
|
Layout.row: 14
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ Rectangle {
|
|||||||
bottomPadding: 5
|
bottomPadding: 5
|
||||||
text: parent.section
|
text: parent.section
|
||||||
color: theme.chatDrawerSectionHeader
|
color: theme.chatDrawerSectionHeader
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmallest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Accessible.role: Accessible.ComboBox
|
|
||||||
Accessible.name: currentModelName()
|
Accessible.name: currentModelName()
|
||||||
Accessible.description: qsTr("The top item is the current model")
|
Accessible.description: qsTr("The top item is the current model")
|
||||||
onActivated: function (index) {
|
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))
|
text: "%1 – %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedTextColor
|
color: theme.mutedTextColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
visible: model.updating
|
visible: model.updating
|
||||||
@ -105,7 +105,7 @@ Rectangle {
|
|||||||
text: qsTr("Updating")
|
text: qsTr("Updating")
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.accentColor
|
color: theme.accentColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ Rectangle {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.maximumWidth: 1530
|
Layout.maximumWidth: 1530
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.topMargin: 20
|
||||||
spacing: 30
|
spacing: 30
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
@ -19,20 +19,30 @@ MySettingsTab {
|
|||||||
title: qsTr("LocalDocs")
|
title: qsTr("LocalDocs")
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
spacing: 10
|
spacing: 30
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
color: theme.styledTextColor
|
Layout.bottomMargin: 10
|
||||||
font.pixelSize: theme.fontSizeLarge
|
color: theme.settingsTitleTextColor
|
||||||
|
font.pixelSize: theme.fontSizeBannerSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
text: "Indexing"
|
text: qsTr("LocalDocs Settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
ColumnLayout {
|
||||||
Layout.bottomMargin: 15
|
spacing: 10
|
||||||
Layout.fillWidth: true
|
Label {
|
||||||
height: 1
|
color: theme.styledTextColor
|
||||||
color: theme.settingsDivider
|
font.pixelSize: theme.fontSizeLarge
|
||||||
|
font.bold: true
|
||||||
|
text: qsTr("Indexing")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: theme.settingsDivider
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@ -81,25 +91,26 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
ColumnLayout {
|
||||||
Layout.topMargin: 15
|
spacing: 10
|
||||||
color: theme.grayRed900
|
Label {
|
||||||
font.pixelSize: theme.fontSizeLarge
|
color: theme.grayRed900
|
||||||
font.bold: true
|
font.pixelSize: theme.fontSizeLarge
|
||||||
text: "Embedding"
|
font.bold: true
|
||||||
}
|
text: qsTr("Embedding")
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.bottomMargin: 15
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
height: 1
|
||||||
height: 1
|
color: theme.grayRed500
|
||||||
color: theme.grayRed500
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
text: qsTr("Use Nomic Embed API")
|
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 {
|
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 {
|
RowLayout {
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: apiKeyLabel
|
id: apiKeyLabel
|
||||||
text: qsTr("Nomic API Key")
|
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) }
|
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,26 +193,27 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
ColumnLayout {
|
||||||
Layout.topMargin: 15
|
spacing: 10
|
||||||
color: theme.grayRed900
|
Label {
|
||||||
font.pixelSize: theme.fontSizeLarge
|
color: theme.grayRed900
|
||||||
font.bold: true
|
font.pixelSize: theme.fontSizeLarge
|
||||||
text: "Display"
|
font.bold: true
|
||||||
}
|
text: qsTr("Display")
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.bottomMargin: 15
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
height: 1
|
||||||
height: 1
|
color: theme.grayRed500
|
||||||
color: theme.grayRed500
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: showReferencesLabel
|
id: showReferencesLabel
|
||||||
text: qsTr("Show sources")
|
text: qsTr("Show Sources")
|
||||||
helpText: qsTr("Shows sources in GUI generated by localdocs")
|
helpText: qsTr("Display the sources used for each response.")
|
||||||
}
|
}
|
||||||
MyCheckBox {
|
MyCheckBox {
|
||||||
id: showReferencesBox
|
id: showReferencesBox
|
||||||
@ -178,19 +224,20 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
ColumnLayout {
|
||||||
Layout.topMargin: 15
|
spacing: 10
|
||||||
color: theme.styledTextColor
|
Label {
|
||||||
font.pixelSize: theme.fontSizeLarge
|
color: theme.styledTextColor
|
||||||
font.bold: true
|
font.pixelSize: theme.fontSizeLarge
|
||||||
text: "Advanced"
|
font.bold: true
|
||||||
}
|
text: qsTr("Advanced")
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.bottomMargin: 15
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
height: 1
|
||||||
height: 1
|
color: theme.settingsDivider
|
||||||
color: theme.settingsDivider
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
|
@ -307,7 +307,7 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
visible: {
|
visible: {
|
||||||
@ -322,7 +322,7 @@ Rectangle {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
font.family: "monospace"
|
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))
|
text: "%1 – %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.styledTextColor2
|
color: theme.styledTextColor2
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: model.embeddingModel
|
text: model.embeddingModel
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
visible: Qt.formatDateTime(model.lastUpdate) !== ""
|
visible: Qt.formatDateTime(model.lastUpdate) !== ""
|
||||||
text: Qt.formatDateTime(model.lastUpdate)
|
text: Qt.formatDateTime(model.lastUpdate)
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedTextColor
|
color: theme.mutedTextColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
visible: model.currentEmbeddingsToIndex !== 0
|
visible: model.currentEmbeddingsToIndex !== 0
|
||||||
@ -354,7 +354,7 @@ Rectangle {
|
|||||||
+ model.totalEmbeddingsToIndex + " embeddings"
|
+ model.totalEmbeddingsToIndex + " embeddings"
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
color: theme.mutedTextColor
|
color: theme.mutedTextColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,53 +400,29 @@ Rectangle {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: 30
|
spacing: 30
|
||||||
Layout.leftMargin: 15
|
Layout.leftMargin: 15
|
||||||
|
Layout.rightMargin: 15
|
||||||
Layout.topMargin: 15
|
Layout.topMargin: 15
|
||||||
Text {
|
MyTextButton {
|
||||||
text: qsTr("Remove")
|
text: qsTr("Remove")
|
||||||
elide: Text.ElideRight
|
|
||||||
color: theme.red500
|
color: theme.red500
|
||||||
font.bold: true
|
onClick: LocalDocs.removeFolder(collection, folder_path)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
Text {
|
MyTextButton {
|
||||||
Layout.alignment: Qt.AlignRight
|
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
|
visible: model.forceIndexing
|
||||||
text: qsTr("Update")
|
text: qsTr("Update")
|
||||||
elide: Text.ElideRight
|
color: theme.green500
|
||||||
color: theme.red500
|
onClick: { LocalDocs.forceIndexing(collection); }
|
||||||
font.bold: true
|
tooltip: qsTr("Update the collection to the new version. This is a slow operation.")
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ MySettingsTab {
|
|||||||
onRestoreDefaultsClicked: {
|
onRestoreDefaultsClicked: {
|
||||||
MySettings.restoreModelDefaults(root.currentModelInfo);
|
MySettings.restoreModelDefaults(root.currentModelInfo);
|
||||||
}
|
}
|
||||||
title: qsTr("Model/Character Settings")
|
title: qsTr("Model")
|
||||||
contentItem: GridLayout {
|
contentItem: GridLayout {
|
||||||
id: root
|
id: root
|
||||||
columns: 3
|
columns: 3
|
||||||
@ -23,32 +23,14 @@ MySettingsTab {
|
|||||||
property var currentModelId: comboBox.currentValue
|
property var currentModelId: comboBox.currentValue
|
||||||
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
|
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
|
||||||
|
|
||||||
ColumnLayout {
|
Label {
|
||||||
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
|
|
||||||
Layout.row: 1
|
Layout.row: 1
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
text: qsTr("Model/Character")
|
Layout.bottomMargin: 10
|
||||||
helpText: qsTr("Select or clone a model and change its settings")
|
color: theme.settingsTitleTextColor
|
||||||
|
font.pixelSize: theme.fontSizeBannerSmall
|
||||||
|
font.bold: true
|
||||||
|
text: qsTr("Model Settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@ -56,7 +38,6 @@ MySettingsTab {
|
|||||||
Layout.row: 2
|
Layout.row: 2
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
Layout.columnSpan: 2
|
Layout.columnSpan: 2
|
||||||
height: label.height + 20
|
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
MyComboBox {
|
MyComboBox {
|
||||||
@ -122,9 +103,7 @@ MySettingsTab {
|
|||||||
Layout.topMargin: 15
|
Layout.topMargin: 15
|
||||||
spacing: 10
|
spacing: 10
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: uniqueNameLabel
|
text: qsTr("Name")
|
||||||
text: qsTr("Unique Name")
|
|
||||||
helpText: qsTr("Must contain a non-empty unique name")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +137,6 @@ MySettingsTab {
|
|||||||
|
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
text: qsTr("Model File")
|
text: qsTr("Model File")
|
||||||
helpText: qsTr("The filename of the selected model")
|
|
||||||
Layout.row: 5
|
Layout.row: 5
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
Layout.topMargin: 15
|
Layout.topMargin: 15
|
||||||
@ -177,7 +155,7 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("System Prompt")
|
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.row: 7
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
Layout.topMargin: 15
|
Layout.topMargin: 15
|
||||||
@ -212,9 +190,6 @@ MySettingsTab {
|
|||||||
MySettings.setModelSystemPrompt(root.currentModelInfo, text)
|
MySettings.setModelSystemPrompt(root.currentModelInfo, text)
|
||||||
}
|
}
|
||||||
Accessible.role: Accessible.EditableText
|
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 {
|
MySettingsLabel {
|
||||||
id: promptTemplateLabel
|
id: promptTemplateLabel
|
||||||
text: qsTr("Prompt Template")
|
text: qsTr("Prompt Template")
|
||||||
helpText: qsTr("The template that wraps every prompt")
|
helpText: qsTr("The template that wraps every prompt.")
|
||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: promptTemplateLabelHelp
|
id: promptTemplateLabelHelp
|
||||||
@ -271,9 +246,6 @@ MySettingsTab {
|
|||||||
Accessible.role: Accessible.EditableText
|
Accessible.role: Accessible.EditableText
|
||||||
Accessible.name: promptTemplateLabel.text
|
Accessible.name: promptTemplateLabel.text
|
||||||
Accessible.description: promptTemplateLabelHelp.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
|
id: contextLengthLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Context Length")
|
text: qsTr("Context Length")
|
||||||
helpText: qsTr("Conversation context window")
|
helpText: qsTr("Number of input and output tokens the model sees.")
|
||||||
Layout.row: 0
|
Layout.row: 0
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
@ -378,7 +350,7 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: tempLabel
|
id: tempLabel
|
||||||
text: qsTr("Temperature")
|
text: qsTr("Temperature")
|
||||||
helpText: qsTr("The temperature for model token generation")
|
helpText: qsTr("Randomness of model output. Higher -> more variation.")
|
||||||
Layout.row: 1
|
Layout.row: 1
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
}
|
}
|
||||||
@ -422,8 +394,8 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: topPLabel
|
id: topPLabel
|
||||||
text: qsTr("Top P")
|
text: qsTr("Top-P")
|
||||||
helpText: qsTr("Prevents choosing highly unlikely tokens")
|
helpText: qsTr("Nucleus Sampling factor. Lower -> more predicatable.")
|
||||||
Layout.row: 2
|
Layout.row: 2
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
@ -432,7 +404,7 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.topP
|
text: root.currentModelInfo.topP
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
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
|
ToolTip.visible: hovered
|
||||||
Layout.row: 2
|
Layout.row: 2
|
||||||
Layout.column: 1
|
Layout.column: 1
|
||||||
@ -466,8 +438,8 @@ MySettingsTab {
|
|||||||
}
|
}
|
||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: minPLabel
|
id: minPLabel
|
||||||
text: qsTr("Min P")
|
text: qsTr("Min-P")
|
||||||
helpText: qsTr("Minimum relative probability")
|
helpText: qsTr("Minimum token probability. Higher -> more predictable.")
|
||||||
Layout.row: 3
|
Layout.row: 3
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
@ -512,8 +484,8 @@ MySettingsTab {
|
|||||||
MySettingsLabel {
|
MySettingsLabel {
|
||||||
id: topKLabel
|
id: topKLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Top K")
|
text: qsTr("Top-K")
|
||||||
helpText: qsTr("Size of selection pool for tokens")
|
helpText: qsTr("Size of selection pool for tokens.")
|
||||||
Layout.row: 2
|
Layout.row: 2
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
}
|
}
|
||||||
@ -523,7 +495,7 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.topK
|
text: root.currentModelInfo.topK
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
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
|
ToolTip.visible: hovered
|
||||||
Layout.row: 2
|
Layout.row: 2
|
||||||
Layout.column: 3
|
Layout.column: 3
|
||||||
@ -559,7 +531,7 @@ MySettingsTab {
|
|||||||
id: maxLengthLabel
|
id: maxLengthLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Max Length")
|
text: qsTr("Max Length")
|
||||||
helpText: qsTr("Maximum length of response in tokens")
|
helpText: qsTr("Maximum response length, in tokens.")
|
||||||
Layout.row: 0
|
Layout.row: 0
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
}
|
}
|
||||||
@ -569,8 +541,6 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.maxLength
|
text: root.currentModelInfo.maxLength
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
ToolTip.text: qsTr("Maximum length of response in tokens")
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
Layout.row: 0
|
Layout.row: 0
|
||||||
Layout.column: 3
|
Layout.column: 3
|
||||||
validator: IntValidator {
|
validator: IntValidator {
|
||||||
@ -606,7 +576,7 @@ MySettingsTab {
|
|||||||
id: batchSizeLabel
|
id: batchSizeLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Prompt Batch Size")
|
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.row: 1
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
@ -616,7 +586,7 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.promptBatchSize
|
text: root.currentModelInfo.promptBatchSize
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
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
|
ToolTip.visible: hovered
|
||||||
Layout.row: 1
|
Layout.row: 1
|
||||||
Layout.column: 1
|
Layout.column: 1
|
||||||
@ -652,7 +622,7 @@ MySettingsTab {
|
|||||||
id: repeatPenaltyLabel
|
id: repeatPenaltyLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Repeat Penalty")
|
text: qsTr("Repeat Penalty")
|
||||||
helpText: qsTr("Penalize repetitiveness")
|
helpText: qsTr("Repetition penalty factor. Set to 1 to disable.")
|
||||||
Layout.row: 4
|
Layout.row: 4
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
}
|
}
|
||||||
@ -662,8 +632,6 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.repeatPenalty
|
text: root.currentModelInfo.repeatPenalty
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
Layout.row: 4
|
Layout.row: 4
|
||||||
Layout.column: 3
|
Layout.column: 3
|
||||||
validator: DoubleValidator {
|
validator: DoubleValidator {
|
||||||
@ -698,7 +666,7 @@ MySettingsTab {
|
|||||||
id: repeatPenaltyTokensLabel
|
id: repeatPenaltyTokensLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("Repeat Penalty Tokens")
|
text: qsTr("Repeat Penalty Tokens")
|
||||||
helpText: qsTr("Length to apply penalty")
|
helpText: qsTr("Number of previous tokens used for penalty.")
|
||||||
Layout.row: 3
|
Layout.row: 3
|
||||||
Layout.column: 2
|
Layout.column: 2
|
||||||
}
|
}
|
||||||
@ -708,8 +676,6 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.repeatPenaltyTokens
|
text: root.currentModelInfo.repeatPenaltyTokens
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
ToolTip.text: qsTr("How far back in output to apply repeat penalty")
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
Layout.row: 3
|
Layout.row: 3
|
||||||
Layout.column: 3
|
Layout.column: 3
|
||||||
validator: IntValidator {
|
validator: IntValidator {
|
||||||
@ -745,7 +711,7 @@ MySettingsTab {
|
|||||||
id: gpuLayersLabel
|
id: gpuLayersLabel
|
||||||
visible: !root.currentModelInfo.isOnline
|
visible: !root.currentModelInfo.isOnline
|
||||||
text: qsTr("GPU Layers")
|
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.row: 4
|
||||||
Layout.column: 0
|
Layout.column: 0
|
||||||
}
|
}
|
||||||
@ -755,7 +721,7 @@ MySettingsTab {
|
|||||||
text: root.currentModelInfo.gpuLayers
|
text: root.currentModelInfo.gpuLayers
|
||||||
font.pixelSize: theme.fontSizeLarge
|
font.pixelSize: theme.fontSizeLarge
|
||||||
color: theme.textColor
|
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
|
ToolTip.visible: hovered
|
||||||
Layout.row: 4
|
Layout.row: 4
|
||||||
Layout.column: 1
|
Layout.column: 1
|
||||||
|
@ -180,13 +180,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("File size")
|
text: qsTr("File size")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: filesize
|
text: filesize
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,13 +202,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("RAM required")
|
text: qsTr("RAM required")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: ramrequired + qsTr(" GB")
|
text: ramrequired + qsTr(" GB")
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,13 +224,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Parameters")
|
text: qsTr("Parameters")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: parameters
|
text: parameters
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,13 +246,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Quant")
|
text: qsTr("Quant")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: quant
|
text: quant
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,13 +268,13 @@ Rectangle {
|
|||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Type")
|
text: qsTr("Type")
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
color: theme.mutedDarkTextColor
|
color: theme.mutedDarkTextColor
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: type
|
text: type
|
||||||
color: theme.textColor
|
color: theme.textColor
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
font.pixelSize: theme.fontSizeSmall
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ ColumnLayout {
|
|||||||
Label {
|
Label {
|
||||||
id: mainTextLabel
|
id: mainTextLabel
|
||||||
color: theme.settingsTitleTextColor
|
color: theme.settingsTitleTextColor
|
||||||
font.pixelSize: theme.fontSizeSmall
|
font.pixelSize: theme.fontSizeLarger
|
||||||
font.bold: true
|
font.bold: true
|
||||||
onLinkActivated: function(link) {
|
onLinkActivated: function(link) {
|
||||||
root.linkActivated(link);
|
root.linkActivated(link);
|
||||||
@ -28,12 +28,13 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
id: helpTextLabel
|
id: helpTextLabel
|
||||||
|
visible: text !== ""
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
color: theme.settingsTitleTextColor
|
color: theme.settingsTitleTextColor
|
||||||
text: mainTextLabel.text
|
font.pixelSize: theme.fontSizeLarge
|
||||||
font.pixelSize: theme.fontSizeSmaller
|
|
||||||
font.bold: false
|
font.bold: false
|
||||||
|
|
||||||
onLinkActivated: function(link) {
|
onLinkActivated: function(link) {
|
||||||
root.linkActivated(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
|
visible: myButton.toggled
|
||||||
border.color: myButton.toggledColor
|
border.color: myButton.toggledColor
|
||||||
border.width: myButton.toggledWidth
|
border.width: myButton.toggledWidth
|
||||||
radius: 10
|
radius: 8
|
||||||
}
|
}
|
||||||
Image {
|
Image {
|
||||||
id: 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 :
|
property real fontSizeSmallest: 8 * fontScale
|
||||||
MySettings.fontSize === "Medium" ? 17 :
|
property real fontSizeSmaller: 9 * fontScale
|
||||||
22
|
property real fontSizeSmall: 10 * fontScale
|
||||||
|
property real fontSizeMedium: 11 * fontScale
|
||||||
property real fontSizeLargest: MySettings.fontSize === "Small" ? 19 :
|
property real fontSizeLarge: 12 * fontScale
|
||||||
MySettings.fontSize === "Medium" ? 24 :
|
property real fontSizeLarger: 14 * fontScale
|
||||||
26
|
property real fontSizeLargest: 18 * fontScale
|
||||||
|
property real fontSizeBannerSmall: 24 * fontScale**.8
|
||||||
property real fontSizeSmaller: fontSizeLarge - 4
|
property real fontSizeBanner: 48 * fontScale**.8
|
||||||
property real fontSizeSmall: fontSizeLarge - 2
|
|
||||||
property real fontSizeLarger: fontSizeLarge + 2
|
|
||||||
property real fontSizeBannerSmall: fontSizeLargest + 10
|
|
||||||
property real fontSizeBanner: fontSizeLargest + 40
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user