mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-06-20 20:53:23 +00:00
UI and embedding device changes for GPT4All v3.0.0-rc3 (#2477)
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
parent
426aa5eb47
commit
2c8d634b5b
@ -132,39 +132,40 @@ qt_add_qml_module(chat
|
||||
main.qml
|
||||
qml/AddCollectionView.qml
|
||||
qml/AddModelView.qml
|
||||
qml/ApplicationSettings.qml
|
||||
qml/ChatDrawer.qml
|
||||
qml/ChatView.qml
|
||||
qml/CollectionsDrawer.qml
|
||||
qml/HomeView.qml
|
||||
qml/LocalDocsSettings.qml
|
||||
qml/LocalDocsView.qml
|
||||
qml/ModelSettings.qml
|
||||
qml/ModelsView.qml
|
||||
qml/NetworkDialog.qml
|
||||
qml/NewVersionDialog.qml
|
||||
qml/ThumbsDownDialog.qml
|
||||
qml/PopupDialog.qml
|
||||
qml/SettingsView.qml
|
||||
qml/StartupDialog.qml
|
||||
qml/PopupDialog.qml
|
||||
qml/Theme.qml
|
||||
qml/ModelSettings.qml
|
||||
qml/ApplicationSettings.qml
|
||||
qml/LocalDocsSettings.qml
|
||||
qml/LocalDocsView.qml
|
||||
qml/SwitchModelDialog.qml
|
||||
qml/MySettingsTab.qml
|
||||
qml/MySettingsStack.qml
|
||||
qml/MySettingsDestructiveButton.qml
|
||||
qml/MySettingsButton.qml
|
||||
qml/MySettingsLabel.qml
|
||||
qml/MySlug.qml
|
||||
qml/Theme.qml
|
||||
qml/ThumbsDownDialog.qml
|
||||
qml/MyBusyIndicator.qml
|
||||
qml/MyButton.qml
|
||||
qml/MyCheckBox.qml
|
||||
qml/MyComboBox.qml
|
||||
qml/MyDialog.qml
|
||||
qml/MyDirectoryField.qml
|
||||
qml/MyFancyLink.qml
|
||||
qml/MyTextArea.qml
|
||||
qml/MyTextField.qml
|
||||
qml/MyCheckBox.qml
|
||||
qml/MyBusyIndicator.qml
|
||||
qml/MyMiniButton.qml
|
||||
qml/MySettingsButton.qml
|
||||
qml/MySettingsDestructiveButton.qml
|
||||
qml/MySettingsLabel.qml
|
||||
qml/MySettingsStack.qml
|
||||
qml/MySettingsTab.qml
|
||||
qml/MySlug.qml
|
||||
qml/MyTextArea.qml
|
||||
qml/MyTextButton.qml
|
||||
qml/MyTextField.qml
|
||||
qml/MyToolButton.qml
|
||||
qml/MyWelcomeButton.qml
|
||||
RESOURCES
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <QMutexLocker>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QWaitCondition>
|
||||
#include <Qt>
|
||||
#include <QtLogging>
|
||||
@ -340,14 +339,48 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
model->setRequestURL(modelInfo.url());
|
||||
model->setAPIKey(apiKey);
|
||||
m_llModelInfo.resetModel(this, model);
|
||||
} else if (!loadNewModel(modelInfo, modelLoadProps)) {
|
||||
return false; // m_shouldBeLoaded became false
|
||||
}
|
||||
#if defined(DEBUG_MODEL_LOADING)
|
||||
qDebug() << "new model" << m_llmThread.objectName() << m_llModelInfo.model.get();
|
||||
#endif
|
||||
restoreState();
|
||||
#if defined(DEBUG)
|
||||
qDebug() << "modelLoadedChanged" << m_llmThread.objectName();
|
||||
fflush(stdout);
|
||||
#endif
|
||||
emit modelLoadingPercentageChanged(isModelLoaded() ? 1.0f : 0.0f);
|
||||
emit loadedModelInfoChanged();
|
||||
|
||||
modelLoadProps.insert("requestedDevice", MySettings::globalInstance()->device());
|
||||
modelLoadProps.insert("model", modelInfo.filename());
|
||||
Network::globalInstance()->trackChatEvent("model_load", modelLoadProps);
|
||||
} else {
|
||||
if (!m_isServer)
|
||||
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo)); // release back into the store
|
||||
resetModel();
|
||||
emit modelLoadingError(u"Could not find file for model %1"_s.arg(modelInfo.filename()));
|
||||
}
|
||||
|
||||
if (m_llModelInfo.model) {
|
||||
setModelInfo(modelInfo);
|
||||
processSystemPrompt();
|
||||
}
|
||||
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();
|
||||
|
||||
auto requestedDevice = MySettings::globalInstance()->device();
|
||||
auto n_ctx = MySettings::globalInstance()->modelContextLength(modelInfo);
|
||||
QString requestedDevice = MySettings::globalInstance()->device();
|
||||
int n_ctx = MySettings::globalInstance()->modelContextLength(modelInfo);
|
||||
m_ctx.n_ctx = n_ctx;
|
||||
auto ngl = MySettings::globalInstance()->modelGpuLayers(modelInfo);
|
||||
int ngl = MySettings::globalInstance()->modelGpuLayers(modelInfo);
|
||||
|
||||
std::string backend = "auto";
|
||||
#ifdef Q_OS_MAC
|
||||
@ -363,6 +396,9 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
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 {
|
||||
@ -380,7 +416,25 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
modelLoadProps.insert("model_arch", QString::fromStdString(e.arch()));
|
||||
}
|
||||
|
||||
if (m_llModelInfo.model) {
|
||||
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();
|
||||
@ -392,12 +446,6 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -450,7 +498,6 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Report which device we're actually using
|
||||
bool success = m_llModelInfo.model->loadModel(filePath.toStdString(), n_ctx, ngl);
|
||||
|
||||
if (!m_shouldBeLoaded) {
|
||||
@ -468,6 +515,11 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
// 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) {
|
||||
@ -493,7 +545,9 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
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 {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (m_llModelInfo.model->implementation().modelType()[0]) {
|
||||
case 'L': m_llModelType = LLModelType::LLAMA_; break;
|
||||
case 'G': m_llModelType = LLModelType::GPTJ_; break;
|
||||
@ -508,41 +562,8 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
|
||||
}
|
||||
|
||||
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)
|
||||
qDebug() << "new model" << m_llmThread.objectName() << m_llModelInfo.model.get();
|
||||
#endif
|
||||
restoreState();
|
||||
#if defined(DEBUG)
|
||||
qDebug() << "modelLoadedChanged" << m_llmThread.objectName();
|
||||
fflush(stdout);
|
||||
#endif
|
||||
emit modelLoadingPercentageChanged(isModelLoaded() ? 1.0f : 0.0f);
|
||||
emit loadedModelInfoChanged();
|
||||
|
||||
modelLoadProps.insert("requestedDevice", MySettings::globalInstance()->device());
|
||||
modelLoadProps.insert("model", modelInfo.filename());
|
||||
Network::globalInstance()->trackChatEvent("model_load", modelLoadProps);
|
||||
} else {
|
||||
if (!m_isServer)
|
||||
LLModelStore::globalInstance()->releaseModel(std::move(m_llModelInfo)); // release back into the store
|
||||
resetModel();
|
||||
emit modelLoadingError(u"Could not find file for model %1"_s.arg(modelInfo.filename()));
|
||||
}
|
||||
|
||||
if (m_llModelInfo.model) {
|
||||
setModelInfo(modelInfo);
|
||||
processSystemPrompt();
|
||||
}
|
||||
return bool(m_llModelInfo.model);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
bool ChatLLM::isModelLoaded() const
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QVariantMap>
|
||||
#include <QVector>
|
||||
#include <QtGlobal>
|
||||
|
||||
@ -214,6 +215,8 @@ protected:
|
||||
quint32 m_promptResponseTokens;
|
||||
|
||||
private:
|
||||
bool loadNewModel(const ModelInfo &modelInfo, QVariantMap &modelLoadProps);
|
||||
|
||||
std::string m_response;
|
||||
std::string m_nameResponse;
|
||||
LLModelInfo m_llModelInfo;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
@ -63,9 +64,13 @@ void EmbeddingLLMWorker::wait()
|
||||
|
||||
bool EmbeddingLLMWorker::loadModel()
|
||||
{
|
||||
constexpr int n_ctx = 2048;
|
||||
|
||||
m_nomicAPIKey.clear();
|
||||
m_model = nullptr;
|
||||
|
||||
// TODO(jared): react to setting changes without restarting
|
||||
|
||||
if (MySettings::globalInstance()->localDocsUseRemoteEmbed()) {
|
||||
m_nomicAPIKey = MySettings::globalInstance()->localDocsNomicAPIKey();
|
||||
return true;
|
||||
@ -79,29 +84,86 @@ bool EmbeddingLLMWorker::loadModel()
|
||||
|
||||
QString filePath = embPathFmt.arg(QCoreApplication::applicationDirPath(), LOCAL_EMBEDDING_MODEL);
|
||||
if (!QFileInfo::exists(filePath)) {
|
||||
qWarning() << "WARNING: Local embedding model not found";
|
||||
qWarning() << "embllm WARNING: Local embedding model not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString requestedDevice = MySettings::globalInstance()->localDocsEmbedDevice();
|
||||
std::string backend = "auto";
|
||||
#ifdef Q_OS_MAC
|
||||
if (requestedDevice == "Auto" || requestedDevice == "CPU")
|
||||
backend = "cpu";
|
||||
#else
|
||||
if (requestedDevice.startsWith("CUDA: "))
|
||||
backend = "cuda";
|
||||
#endif
|
||||
|
||||
try {
|
||||
m_model = LLModel::Implementation::construct(filePath.toStdString());
|
||||
m_model = LLModel::Implementation::construct(filePath.toStdString(), backend, n_ctx);
|
||||
} catch (const std::exception &e) {
|
||||
qWarning() << "WARNING: Could not load embedding model:" << e.what();
|
||||
qWarning() << "embllm WARNING: Could not load embedding model:" << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: explicitly loads model on CPU to avoid GPU OOM
|
||||
// TODO(cebtenzzre): support GPU-accelerated embeddings
|
||||
bool success = m_model->loadModel(filePath.toStdString(), 2048, 0);
|
||||
bool actualDeviceIsCPU = true;
|
||||
|
||||
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
||||
if (m_model->implementation().buildVariant() == "metal")
|
||||
actualDeviceIsCPU = false;
|
||||
#else
|
||||
if (requestedDevice != "CPU") {
|
||||
const LLModel::GPUDevice *device = nullptr;
|
||||
std::vector<LLModel::GPUDevice> availableDevices = m_model->availableGPUDevices(0);
|
||||
if (requestedDevice != "Auto") {
|
||||
// Use the selected device
|
||||
for (const LLModel::GPUDevice &d : availableDevices) {
|
||||
if (QString::fromStdString(d.selectionName()) == requestedDevice) {
|
||||
device = &d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string unavail_reason;
|
||||
if (!device) {
|
||||
// GPU not available
|
||||
} else if (!m_model->initializeGPUDevice(device->index, &unavail_reason)) {
|
||||
qWarning().noquote() << "embllm WARNING: Did not use GPU:" << QString::fromStdString(unavail_reason);
|
||||
} else {
|
||||
actualDeviceIsCPU = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool success = m_model->loadModel(filePath.toStdString(), n_ctx, 100);
|
||||
|
||||
// CPU fallback
|
||||
if (!actualDeviceIsCPU && !success) {
|
||||
// llama_init_from_file returned nullptr
|
||||
qWarning() << "embllm WARNING: Did not use GPU: GPU loading failed (out of VRAM?)";
|
||||
|
||||
if (backend == "cuda") {
|
||||
// For CUDA, make sure we don't use the GPU at all - ngl=0 still offloads matmuls
|
||||
try {
|
||||
m_model = LLModel::Implementation::construct(filePath.toStdString(), "auto", n_ctx);
|
||||
} catch (const std::exception &e) {
|
||||
qWarning() << "embllm WARNING: Could not load embedding model:" << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
success = m_model->loadModel(filePath.toStdString(), n_ctx, 0);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "WARNING: Could not load embedding model";
|
||||
qWarning() << "embllm WARNING: Could not load embedding model";
|
||||
delete m_model;
|
||||
m_model = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_model->supportsEmbedding()) {
|
||||
qWarning() << "WARNING: Model type does not support embeddings";
|
||||
qWarning() << "embllm WARNING: Model type does not support embeddings";
|
||||
delete m_model;
|
||||
m_model = nullptr;
|
||||
return false;
|
||||
@ -128,7 +190,7 @@ std::vector<float> EmbeddingLLMWorker::generateQueryEmbedding(const QString &tex
|
||||
std::vector<float> embedding(m_model->embeddingSize());
|
||||
|
||||
try {
|
||||
m_model->embed({text.toStdString()}, embedding.data(), true);
|
||||
m_model->embed({text.toStdString()}, embedding.data(), /*isRetrieval*/ true);
|
||||
} catch (const std::exception &e) {
|
||||
qWarning() << "WARNING: LLModel::embed failed:" << e.what();
|
||||
return {};
|
||||
@ -203,26 +265,34 @@ void EmbeddingLLMWorker::docEmbeddingsRequested(const QVector<EmbeddingChunk> &c
|
||||
if (!isNomic) {
|
||||
QVector<EmbeddingResult> results;
|
||||
results.reserve(chunks.size());
|
||||
std::vector<std::string> texts;
|
||||
texts.reserve(chunks.size());
|
||||
for (const auto &c: chunks) {
|
||||
EmbeddingResult result;
|
||||
result.model = c.model;
|
||||
result.folder_id = c.folder_id;
|
||||
result.chunk_id = c.chunk_id;
|
||||
// TODO(cebtenzzre): take advantage of batched embeddings
|
||||
result.embedding.resize(m_model->embeddingSize());
|
||||
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({c.chunk.toStdString()}, result.embedding.data(), false);
|
||||
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));
|
||||
|
||||
results << result;
|
||||
}
|
||||
emit embeddingsGenerated(results);
|
||||
return;
|
||||
};
|
||||
|
@ -204,7 +204,7 @@ Window {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: MySettings.fontSize === "Small" ? 86 : 100
|
||||
width: 16 + 52 * theme.fontScale
|
||||
color: theme.viewBarBackground
|
||||
|
||||
ColumnLayout {
|
||||
@ -213,20 +213,20 @@ Window {
|
||||
anchors.topMargin: 30
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
Layout.margins: 0
|
||||
spacing: 18
|
||||
spacing: 16
|
||||
|
||||
MyToolButton {
|
||||
id: homeButton
|
||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
Layout.preferredHeight: 38 * theme.fontScale
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
toggledWidth: 0
|
||||
toggled: homeView.isShown()
|
||||
toggledColor: theme.iconBackgroundViewBarToggled
|
||||
imageWidth: 34
|
||||
imageHeight: 34
|
||||
imageWidth: 25 * theme.fontScale
|
||||
imageHeight: 25 * theme.fontScale
|
||||
source: "qrc:/gpt4all/icons/home.svg"
|
||||
Accessible.name: qsTr("Home view")
|
||||
Accessible.description: qsTr("Home view of application")
|
||||
@ -238,10 +238,10 @@ Window {
|
||||
Text {
|
||||
Layout.topMargin: -20
|
||||
text: qsTr("Home")
|
||||
font.pixelSize: theme.fontSizeLargeCapped
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.bold: true
|
||||
color: homeButton.hovered ? homeButton.backgroundColorHovered : homeButton.backgroundColor
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
TapHandler {
|
||||
onTapped: function(eventPoint, button) {
|
||||
@ -254,14 +254,14 @@ Window {
|
||||
id: chatButton
|
||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
Layout.preferredHeight: 38 * theme.fontScale
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
toggledWidth: 0
|
||||
toggled: chatView.isShown()
|
||||
toggledColor: theme.iconBackgroundViewBarToggled
|
||||
imageWidth: 34
|
||||
imageHeight: 34
|
||||
imageWidth: 25 * theme.fontScale
|
||||
imageHeight: 25 * theme.fontScale
|
||||
source: "qrc:/gpt4all/icons/chat.svg"
|
||||
Accessible.name: qsTr("Chat view")
|
||||
Accessible.description: qsTr("Chat view to interact with models")
|
||||
@ -273,10 +273,10 @@ Window {
|
||||
Text {
|
||||
Layout.topMargin: -20
|
||||
text: qsTr("Chats")
|
||||
font.pixelSize: theme.fontSizeLargeCapped
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.bold: true
|
||||
color: chatButton.hovered ? chatButton.backgroundColorHovered : chatButton.backgroundColor
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
TapHandler {
|
||||
onTapped: function(eventPoint, button) {
|
||||
@ -289,13 +289,13 @@ Window {
|
||||
id: modelsButton
|
||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
Layout.preferredHeight: 38 * theme.fontScale
|
||||
toggledWidth: 0
|
||||
toggled: modelsView.isShown()
|
||||
toggledColor: theme.iconBackgroundViewBarToggled
|
||||
imageWidth: 34
|
||||
imageHeight: 34
|
||||
imageWidth: 25 * theme.fontScale
|
||||
imageHeight: 25 * theme.fontScale
|
||||
source: "qrc:/gpt4all/icons/models.svg"
|
||||
Accessible.name: qsTr("Models")
|
||||
Accessible.description: qsTr("Models view for installed models")
|
||||
@ -307,10 +307,10 @@ Window {
|
||||
Text {
|
||||
Layout.topMargin: -20
|
||||
text: qsTr("Models")
|
||||
font.pixelSize: theme.fontSizeLargeCapped
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.bold: true
|
||||
color: modelsButton.hovered ? modelsButton.backgroundColorHovered : modelsButton.backgroundColor
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
TapHandler {
|
||||
onTapped: function(eventPoint, button) {
|
||||
@ -323,13 +323,13 @@ Window {
|
||||
id: localdocsButton
|
||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
Layout.preferredHeight: 38 * theme.fontScale
|
||||
toggledWidth: 0
|
||||
toggledColor: theme.iconBackgroundViewBarToggled
|
||||
toggled: localDocsView.isShown()
|
||||
imageWidth: 34
|
||||
imageHeight: 34
|
||||
imageWidth: 25 * theme.fontScale
|
||||
imageHeight: 25 * theme.fontScale
|
||||
source: "qrc:/gpt4all/icons/db.svg"
|
||||
Accessible.name: qsTr("LocalDocs")
|
||||
Accessible.description: qsTr("LocalDocs view to configure and use local docs")
|
||||
@ -341,10 +341,10 @@ Window {
|
||||
Text {
|
||||
Layout.topMargin: -20
|
||||
text: qsTr("LocalDocs")
|
||||
font.pixelSize: theme.fontSizeLargeCapped
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.bold: true
|
||||
color: localdocsButton.hovered ? localdocsButton.backgroundColorHovered : localdocsButton.backgroundColor
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
TapHandler {
|
||||
onTapped: function(eventPoint, button) {
|
||||
@ -357,13 +357,13 @@ Window {
|
||||
id: settingsButton
|
||||
backgroundColor: toggled ? theme.iconBackgroundViewBarHovered : theme.iconBackgroundViewBar
|
||||
backgroundColorHovered: theme.iconBackgroundViewBarHovered
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
Layout.preferredHeight: 38 * theme.fontScale
|
||||
toggledWidth: 0
|
||||
toggledColor: theme.iconBackgroundViewBarToggled
|
||||
toggled: settingsView.isShown()
|
||||
imageWidth: 34
|
||||
imageHeight: 34
|
||||
imageWidth: 25 * theme.fontScale
|
||||
imageHeight: 25 * theme.fontScale
|
||||
source: "qrc:/gpt4all/icons/settings.svg"
|
||||
Accessible.name: qsTr("Settings")
|
||||
Accessible.description: qsTr("Settings view for application configuration")
|
||||
@ -375,10 +375,10 @@ Window {
|
||||
Text {
|
||||
Layout.topMargin: -20
|
||||
text: qsTr("Settings")
|
||||
font.pixelSize: theme.fontSizeLargeCapped
|
||||
font.pixelSize: theme.fontSizeMedium
|
||||
font.bold: true
|
||||
color: settingsButton.hovered ? settingsButton.backgroundColorHovered : settingsButton.backgroundColor
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredWidth: 38 * theme.fontScale
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
TapHandler {
|
||||
onTapped: function(eventPoint, button) {
|
||||
|
@ -47,6 +47,7 @@ static const QVariantMap basicDefaults {
|
||||
{ "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } },
|
||||
{ "localdocs/useRemoteEmbed", false },
|
||||
{ "localdocs/nomicAPIKey", "" },
|
||||
{ "localdocs/embedDevice", "Auto" },
|
||||
{ "network/attribution", "" },
|
||||
};
|
||||
|
||||
@ -77,6 +78,22 @@ static QString defaultLocalModelsPath()
|
||||
return canonicalLocalPath;
|
||||
}
|
||||
|
||||
static QStringList getDevices(bool skipKompute = false)
|
||||
{
|
||||
QStringList deviceList { "Auto" };
|
||||
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
||||
deviceList << "Metal";
|
||||
#else
|
||||
std::vector<LLModel::GPUDevice> devices = LLModel::Implementation::availableGPUDevices();
|
||||
for (LLModel::GPUDevice &d : devices) {
|
||||
if (!skipKompute || strcmp(d.backend, "kompute"))
|
||||
deviceList << QString::fromStdString(d.selectionName());
|
||||
}
|
||||
#endif
|
||||
deviceList << "CPU";
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
class MyPrivateSettings: public MySettings { };
|
||||
Q_GLOBAL_STATIC(MyPrivateSettings, settingsInstance)
|
||||
MySettings *MySettings::globalInstance()
|
||||
@ -85,18 +102,10 @@ MySettings *MySettings::globalInstance()
|
||||
}
|
||||
|
||||
MySettings::MySettings()
|
||||
: QObject{nullptr}
|
||||
: QObject(nullptr)
|
||||
, m_deviceList(getDevices())
|
||||
, m_embeddingsDeviceList(getDevices(/*skipKompute*/ true))
|
||||
{
|
||||
QVector<QString> deviceList{ "Auto" };
|
||||
#if defined(Q_OS_MAC) && defined(__aarch64__)
|
||||
deviceList << "Metal";
|
||||
#else
|
||||
std::vector<LLModel::GPUDevice> devices = LLModel::Implementation::availableGPUDevices();
|
||||
for (LLModel::GPUDevice &d : devices)
|
||||
deviceList << QString::fromStdString(d.selectionName());
|
||||
#endif
|
||||
deviceList << "CPU";
|
||||
setDeviceList(deviceList);
|
||||
}
|
||||
|
||||
QVariant MySettings::getBasicSetting(const QString &name) const
|
||||
@ -113,17 +122,6 @@ void MySettings::setBasicSetting(const QString &name, const QVariant &value, std
|
||||
QMetaObject::invokeMethod(this, u"%1Changed"_s.arg(signal.value_or(name)).toLatin1().constData());
|
||||
}
|
||||
|
||||
Q_INVOKABLE QVector<QString> MySettings::deviceList() const
|
||||
{
|
||||
return m_deviceList;
|
||||
}
|
||||
|
||||
void MySettings::setDeviceList(const QVector<QString> &value)
|
||||
{
|
||||
m_deviceList = value;
|
||||
emit deviceListChanged();
|
||||
}
|
||||
|
||||
void MySettings::restoreModelDefaults(const ModelInfo &info)
|
||||
{
|
||||
setModelTemperature(info, info.m_temperature);
|
||||
@ -162,6 +160,7 @@ void MySettings::restoreLocalDocsDefaults()
|
||||
setLocalDocsFileExtensions(basicDefaults.value("localdocs/fileExtensions").toStringList());
|
||||
setLocalDocsUseRemoteEmbed(basicDefaults.value("localdocs/useRemoteEmbed").toBool());
|
||||
setLocalDocsNomicAPIKey(basicDefaults.value("localdocs/nomicAPIKey").toString());
|
||||
setLocalDocsEmbedDevice(basicDefaults.value("localdocs/embedDevice").toString());
|
||||
}
|
||||
|
||||
void MySettings::eraseModel(const ModelInfo &info)
|
||||
@ -382,6 +381,7 @@ bool MySettings::localDocsShowReferences() const { return getBasicSetting
|
||||
QStringList MySettings::localDocsFileExtensions() const { return getBasicSetting("localdocs/fileExtensions").toStringList(); }
|
||||
bool MySettings::localDocsUseRemoteEmbed() const { return getBasicSetting("localdocs/useRemoteEmbed").toBool(); }
|
||||
QString MySettings::localDocsNomicAPIKey() const { return getBasicSetting("localdocs/nomicAPIKey" ).toString(); }
|
||||
QString MySettings::localDocsEmbedDevice() const { return getBasicSetting("localdocs/embedDevice" ).toString(); }
|
||||
QString MySettings::networkAttribution() const { return getBasicSetting("network/attribution" ).toString(); }
|
||||
|
||||
void MySettings::setSaveChatsContext(bool value) { setBasicSetting("saveChatsContext", value); }
|
||||
@ -397,6 +397,7 @@ void MySettings::setLocalDocsShowReferences(bool value) { setBasic
|
||||
void MySettings::setLocalDocsFileExtensions(const QStringList &value) { setBasicSetting("localdocs/fileExtensions", value, "localDocsFileExtensions"); }
|
||||
void MySettings::setLocalDocsUseRemoteEmbed(bool value) { setBasicSetting("localdocs/useRemoteEmbed", value, "localDocsUseRemoteEmbed"); }
|
||||
void MySettings::setLocalDocsNomicAPIKey(const QString &value) { setBasicSetting("localdocs/nomicAPIKey", value, "localDocsNomicAPIKey"); }
|
||||
void MySettings::setLocalDocsEmbedDevice(const QString &value) { setBasicSetting("localdocs/embedDevice", value, "localDocsEmbedDevice"); }
|
||||
void MySettings::setNetworkAttribution(const QString &value) { setBasicSetting("network/attribution", value, "networkAttribution"); }
|
||||
|
||||
QString MySettings::modelPath()
|
||||
@ -446,12 +447,11 @@ QString MySettings::device()
|
||||
|
||||
void MySettings::setDevice(const QString &value)
|
||||
{
|
||||
if (device() == value)
|
||||
return;
|
||||
|
||||
if (device() != value) {
|
||||
m_settings.setValue("device", value);
|
||||
emit deviceChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool MySettings::forceMetal() const
|
||||
{
|
||||
@ -460,11 +460,11 @@ bool MySettings::forceMetal() const
|
||||
|
||||
void MySettings::setForceMetal(bool value)
|
||||
{
|
||||
if (m_forceMetal == value)
|
||||
return;
|
||||
if (m_forceMetal != value) {
|
||||
m_forceMetal = value;
|
||||
emit forceMetalChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool MySettings::networkIsActive() const
|
||||
{
|
||||
|
@ -31,11 +31,13 @@ class MySettings : public QObject
|
||||
Q_PROPERTY(QStringList localDocsFileExtensions READ localDocsFileExtensions WRITE setLocalDocsFileExtensions NOTIFY localDocsFileExtensionsChanged)
|
||||
Q_PROPERTY(bool localDocsUseRemoteEmbed READ localDocsUseRemoteEmbed WRITE setLocalDocsUseRemoteEmbed NOTIFY localDocsUseRemoteEmbedChanged)
|
||||
Q_PROPERTY(QString localDocsNomicAPIKey READ localDocsNomicAPIKey WRITE setLocalDocsNomicAPIKey NOTIFY localDocsNomicAPIKeyChanged)
|
||||
Q_PROPERTY(QString localDocsEmbedDevice READ localDocsEmbedDevice WRITE setLocalDocsEmbedDevice NOTIFY localDocsEmbedDeviceChanged)
|
||||
Q_PROPERTY(QString networkAttribution READ networkAttribution WRITE setNetworkAttribution NOTIFY networkAttributionChanged)
|
||||
Q_PROPERTY(bool networkIsActive READ networkIsActive WRITE setNetworkIsActive NOTIFY networkIsActiveChanged)
|
||||
Q_PROPERTY(bool networkUsageStatsActive READ networkUsageStatsActive WRITE setNetworkUsageStatsActive NOTIFY networkUsageStatsActiveChanged)
|
||||
Q_PROPERTY(QString device READ device WRITE setDevice NOTIFY deviceChanged)
|
||||
Q_PROPERTY(QVector<QString> deviceList READ deviceList NOTIFY deviceListChanged)
|
||||
Q_PROPERTY(QStringList deviceList MEMBER m_deviceList CONSTANT)
|
||||
Q_PROPERTY(QStringList embeddingsDeviceList MEMBER m_embeddingsDeviceList CONSTANT)
|
||||
Q_PROPERTY(int networkPort READ networkPort WRITE setNetworkPort NOTIFY networkPortChanged)
|
||||
|
||||
public:
|
||||
@ -138,6 +140,8 @@ public:
|
||||
void setLocalDocsUseRemoteEmbed(bool value);
|
||||
QString localDocsNomicAPIKey() const;
|
||||
void setLocalDocsNomicAPIKey(const QString &value);
|
||||
QString localDocsEmbedDevice() const;
|
||||
void setLocalDocsEmbedDevice(const QString &value);
|
||||
|
||||
// Network settings
|
||||
QString networkAttribution() const;
|
||||
@ -151,9 +155,6 @@ public:
|
||||
int networkPort() const;
|
||||
void setNetworkPort(int value);
|
||||
|
||||
QVector<QString> deviceList() const;
|
||||
void setDeviceList(const QVector<QString> &value);
|
||||
|
||||
Q_SIGNALS:
|
||||
void nameChanged(const ModelInfo &info);
|
||||
void filenameChanged(const ModelInfo &info);
|
||||
@ -185,18 +186,19 @@ Q_SIGNALS:
|
||||
void localDocsFileExtensionsChanged();
|
||||
void localDocsUseRemoteEmbedChanged();
|
||||
void localDocsNomicAPIKeyChanged();
|
||||
void localDocsEmbedDeviceChanged();
|
||||
void networkAttributionChanged();
|
||||
void networkIsActiveChanged();
|
||||
void networkPortChanged();
|
||||
void networkUsageStatsActiveChanged();
|
||||
void attemptModelLoadChanged();
|
||||
void deviceChanged();
|
||||
void deviceListChanged();
|
||||
|
||||
private:
|
||||
QSettings m_settings;
|
||||
bool m_forceMetal;
|
||||
QVector<QString> m_deviceList;
|
||||
const QStringList m_deviceList;
|
||||
const QStringList m_embeddingsDeviceList;
|
||||
|
||||
private:
|
||||
explicit MySettings();
|
||||
|
@ -603,13 +603,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("File size")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: filesize
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -625,13 +625,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("RAM required")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -647,13 +647,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Parameters")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: parameters !== "" ? parameters : "?"
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -669,13 +669,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Quant")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: quant
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -691,13 +691,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Type")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: type
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +62,19 @@ MySettingsTab {
|
||||
rowSpacing: 30
|
||||
columnSpacing: 10
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
Layout.bottomMargin: 10
|
||||
color: theme.settingsTitleTextColor
|
||||
font.pixelSize: theme.fontSizeBannerSmall
|
||||
font.bold: true
|
||||
text: qsTr("Application Settings")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 3
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
@ -72,7 +82,7 @@ MySettingsTab {
|
||||
color: theme.styledTextColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "General"
|
||||
text: qsTr("General")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -85,22 +95,21 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: themeLabel
|
||||
text: qsTr("Theme")
|
||||
helpText: qsTr("Customize the colors of GPT4All")
|
||||
Layout.row: 1
|
||||
helpText: qsTr("The application color scheme.")
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
}
|
||||
MyComboBox {
|
||||
id: themeBox
|
||||
Layout.row: 1
|
||||
Layout.row: 2
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 200
|
||||
Layout.maximumWidth: 200
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: [qsTr("Dark"), qsTr("Light"), qsTr("LegacyDark")]
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: qsTr("Color theme")
|
||||
Accessible.description: qsTr("Color theme for the chat client to use")
|
||||
Accessible.name: themeLabel.text
|
||||
Accessible.description: themeLabel.helpText
|
||||
function updateModel() {
|
||||
themeBox.currentIndex = themeBox.indexOfValue(MySettings.chatTheme);
|
||||
}
|
||||
@ -120,22 +129,21 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: fontLabel
|
||||
text: qsTr("Font Size")
|
||||
helpText: qsTr("How big your font is displayed")
|
||||
Layout.row: 2
|
||||
helpText: qsTr("The size of text in the application.")
|
||||
Layout.row: 3
|
||||
Layout.column: 0
|
||||
}
|
||||
MyComboBox {
|
||||
id: fontBox
|
||||
Layout.row: 2
|
||||
Layout.row: 3
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 200
|
||||
Layout.maximumWidth: 200
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: ["Small", "Medium", "Large"]
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: qsTr("Font size")
|
||||
Accessible.description: qsTr("Font size of the chat client")
|
||||
Accessible.name: fontLabel.text
|
||||
Accessible.description: fontLabel.helpText
|
||||
function updateModel() {
|
||||
fontBox.currentIndex = fontBox.indexOfValue(MySettings.fontSize);
|
||||
}
|
||||
@ -155,59 +163,54 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: deviceLabel
|
||||
text: qsTr("Device")
|
||||
helpText: qsTr("The hardware device used to load the model")
|
||||
Layout.row: 3
|
||||
helpText: qsTr('The compute device used for text generation. "Auto" uses Vulkan or Metal.')
|
||||
Layout.row: 4
|
||||
Layout.column: 0
|
||||
}
|
||||
MyComboBox {
|
||||
id: deviceBox
|
||||
Layout.row: 3
|
||||
Layout.row: 4
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 400
|
||||
Layout.maximumWidth: 400
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: MySettings.deviceList
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: qsTr("Device")
|
||||
Accessible.description: qsTr("Device of the chat client")
|
||||
Accessible.name: deviceLabel.text
|
||||
Accessible.description: deviceLabel.helpText
|
||||
function updateModel() {
|
||||
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device);
|
||||
}
|
||||
Component.onCompleted: {
|
||||
deviceBox.updateModel()
|
||||
deviceBox.updateModel();
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onDeviceChanged() {
|
||||
deviceBox.updateModel()
|
||||
}
|
||||
function onDeviceListChanged() {
|
||||
deviceBox.updateModel()
|
||||
deviceBox.updateModel();
|
||||
}
|
||||
}
|
||||
onActivated: {
|
||||
MySettings.device = deviceBox.currentText
|
||||
MySettings.device = deviceBox.currentText;
|
||||
}
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: defaultModelLabel
|
||||
text: qsTr("Default model")
|
||||
helpText: qsTr("The preferred default model")
|
||||
Layout.row: 4
|
||||
text: qsTr("Default Model")
|
||||
helpText: qsTr("The preferred model for new chats. Also used as the local server fallback.")
|
||||
Layout.row: 5
|
||||
Layout.column: 0
|
||||
}
|
||||
MyComboBox {
|
||||
id: comboBox
|
||||
Layout.row: 4
|
||||
Layout.row: 5
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 400
|
||||
Layout.maximumWidth: 400
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: ModelList.userDefaultModelList
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: qsTr("Default model")
|
||||
Accessible.description: qsTr("Default model to use; the first item is the current default model")
|
||||
Accessible.name: defaultModelLabel.text
|
||||
Accessible.description: defaultModelLabel.helpText
|
||||
function updateModel() {
|
||||
comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel);
|
||||
}
|
||||
@ -226,14 +229,14 @@ MySettingsTab {
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: modelPathLabel
|
||||
text: qsTr("Download path")
|
||||
helpText: qsTr("The download folder for models")
|
||||
Layout.row: 5
|
||||
text: qsTr("Download Path")
|
||||
helpText: qsTr("Where to store local models and the LocalDocs database.")
|
||||
Layout.row: 6
|
||||
Layout.column: 0
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.row: 5
|
||||
Layout.row: 6
|
||||
Layout.column: 2
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.minimumWidth: 400
|
||||
@ -245,11 +248,8 @@ MySettingsTab {
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
implicitWidth: 300
|
||||
Layout.fillWidth: true
|
||||
ToolTip.text: qsTr("Path where model files will be downloaded to")
|
||||
ToolTip.visible: hovered
|
||||
Accessible.role: Accessible.ToolTip
|
||||
Accessible.name: modelPathDisplayField.text
|
||||
Accessible.description: ToolTip.text
|
||||
Accessible.name: modelPathLabel.text
|
||||
Accessible.description: modelPathLabel.helpText
|
||||
onEditingFinished: {
|
||||
if (isValid) {
|
||||
MySettings.modelPath = modelPathDisplayField.text
|
||||
@ -271,29 +271,32 @@ MySettingsTab {
|
||||
|
||||
MySettingsLabel {
|
||||
id: dataLakeLabel
|
||||
text: qsTr("Opensource Datalake")
|
||||
helpText: qsTr("Send your data to the GPT4All Open Source Datalake.")
|
||||
Layout.row: 6
|
||||
text: qsTr("Enable Datalake")
|
||||
helpText: qsTr("Send chats and feedback to the GPT4All Open-Source Datalake.")
|
||||
Layout.row: 7
|
||||
Layout.column: 0
|
||||
}
|
||||
MyCheckBox {
|
||||
id: dataLakeBox
|
||||
Layout.row: 6
|
||||
Layout.row: 7
|
||||
Layout.column: 2
|
||||
Layout.alignment: Qt.AlignRight
|
||||
checked: MySettings.networkIsActive
|
||||
onClicked: {
|
||||
if (MySettings.networkIsActive) {
|
||||
MySettings.networkIsActive = false
|
||||
} else
|
||||
networkDialog.open()
|
||||
Component.onCompleted: { dataLakeBox.checked = MySettings.networkIsActive; }
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onNetworkIsActiveChanged() { dataLakeBox.checked = MySettings.networkIsActive; }
|
||||
}
|
||||
onClicked: {
|
||||
if (MySettings.networkIsActive)
|
||||
MySettings.networkIsActive = false;
|
||||
else
|
||||
networkDialog.open();
|
||||
dataLakeBox.checked = MySettings.networkIsActive;
|
||||
}
|
||||
ToolTip.text: qsTr("Reveals a dialogue where you can opt-in for sharing data over network")
|
||||
ToolTip.visible: hovered
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.row: 7
|
||||
Layout.row: 8
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 3
|
||||
Layout.fillWidth: true
|
||||
@ -302,7 +305,7 @@ MySettingsTab {
|
||||
color: theme.styledTextColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "Advanced"
|
||||
text: qsTr("Advanced")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -315,18 +318,16 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: nThreadsLabel
|
||||
text: qsTr("CPU Threads")
|
||||
helpText: qsTr("Number of CPU threads for inference and embedding")
|
||||
Layout.row: 8
|
||||
helpText: qsTr("The number of CPU threads used for inference and embedding.")
|
||||
Layout.row: 9
|
||||
Layout.column: 0
|
||||
}
|
||||
MyTextField {
|
||||
text: MySettings.threadCount
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Amount of processing threads to use bounded by 1 and number of logical processors")
|
||||
ToolTip.visible: hovered
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.row: 8
|
||||
Layout.row: 9
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 200
|
||||
Layout.maximumWidth: 200
|
||||
@ -348,47 +349,43 @@ MySettingsTab {
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: saveChatsContextLabel
|
||||
text: qsTr("Save chat context")
|
||||
helpText: qsTr("Save chat context to disk")
|
||||
Layout.row: 9
|
||||
text: qsTr("Save Chat Context")
|
||||
helpText: qsTr("Save the chat model's state to disk for faster loading. WARNING: Uses ~2GB per chat.")
|
||||
Layout.row: 10
|
||||
Layout.column: 0
|
||||
}
|
||||
MyCheckBox {
|
||||
id: saveChatsContextBox
|
||||
Layout.row: 9
|
||||
Layout.row: 10
|
||||
Layout.column: 2
|
||||
Layout.alignment: Qt.AlignRight
|
||||
checked: MySettings.saveChatsContext
|
||||
onClicked: {
|
||||
MySettings.saveChatsContext = !MySettings.saveChatsContext
|
||||
}
|
||||
ToolTip.text: qsTr("WARNING: Saving chats to disk can be ~2GB per chat")
|
||||
ToolTip.visible: hovered
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: serverChatLabel
|
||||
text: qsTr("Enable API server")
|
||||
helpText: qsTr("A local http server running on local port")
|
||||
Layout.row: 10
|
||||
text: qsTr("Enable Local Server")
|
||||
helpText: qsTr("Expose an OpenAI-Compatible server to localhost. WARNING: Results in increased resource usage.")
|
||||
Layout.row: 11
|
||||
Layout.column: 0
|
||||
}
|
||||
MyCheckBox {
|
||||
id: serverChatBox
|
||||
Layout.row: 10
|
||||
Layout.row: 11
|
||||
Layout.column: 2
|
||||
Layout.alignment: Qt.AlignRight
|
||||
checked: MySettings.serverChat
|
||||
onClicked: {
|
||||
MySettings.serverChat = !MySettings.serverChat
|
||||
}
|
||||
ToolTip.text: qsTr("WARNING: This enables the gui to act as a local REST web server(OpenAI API compliant) for API requests and will increase your RAM usage as well")
|
||||
ToolTip.visible: hovered
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: serverPortLabel
|
||||
text: qsTr("API Server Port:")
|
||||
helpText: qsTr("A local port to run the server (Requires restart")
|
||||
Layout.row: 11
|
||||
text: qsTr("API Server Port")
|
||||
helpText: qsTr("The port to use for the local server. Requires restart.")
|
||||
Layout.row: 12
|
||||
Layout.column: 0
|
||||
}
|
||||
MyTextField {
|
||||
@ -396,9 +393,7 @@ MySettingsTab {
|
||||
text: MySettings.networkPort
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Api server port. WARNING: You need to restart the application for it to take effect")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 11
|
||||
Layout.row: 12
|
||||
Layout.column: 2
|
||||
Layout.minimumWidth: 200
|
||||
Layout.maximumWidth: 200
|
||||
@ -416,8 +411,8 @@ MySettingsTab {
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: serverPortField.text
|
||||
Accessible.description: ToolTip.text
|
||||
Accessible.name: serverPortLabel.text
|
||||
Accessible.description: serverPortLabel.helpText
|
||||
}
|
||||
|
||||
/*MySettingsLabel {
|
||||
@ -441,8 +436,8 @@ MySettingsTab {
|
||||
|
||||
MySettingsLabel {
|
||||
id: updatesLabel
|
||||
text: qsTr("Check for updates")
|
||||
helpText: qsTr("Click to see if an update to the application is available");
|
||||
text: qsTr("Check For Updates")
|
||||
helpText: qsTr("Manually check for an update to GPT4All.");
|
||||
Layout.row: 14
|
||||
Layout.column: 0
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ Rectangle {
|
||||
bottomPadding: 5
|
||||
text: parent.section
|
||||
color: theme.chatDrawerSectionHeader
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmallest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +365,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.ComboBox
|
||||
Accessible.name: currentModelName()
|
||||
Accessible.description: qsTr("The top item is the current model")
|
||||
onActivated: function (index) {
|
||||
|
@ -89,7 +89,7 @@ Rectangle {
|
||||
text: "%1 – %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedTextColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
RowLayout {
|
||||
visible: model.updating
|
||||
@ -105,7 +105,7 @@ Rectangle {
|
||||
text: qsTr("Updating")
|
||||
elide: Text.ElideRight
|
||||
color: theme.accentColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 1530
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 20
|
||||
spacing: 30
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -19,21 +19,31 @@ MySettingsTab {
|
||||
title: qsTr("LocalDocs")
|
||||
contentItem: ColumnLayout {
|
||||
id: root
|
||||
spacing: 10
|
||||
spacing: 30
|
||||
|
||||
Label {
|
||||
Layout.bottomMargin: 10
|
||||
color: theme.settingsTitleTextColor
|
||||
font.pixelSize: theme.fontSizeBannerSmall
|
||||
font.bold: true
|
||||
text: qsTr("LocalDocs Settings")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
color: theme.styledTextColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "Indexing"
|
||||
text: qsTr("Indexing")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.bottomMargin: 15
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: theme.settingsDivider
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
MySettingsLabel {
|
||||
@ -81,25 +91,26 @@ MySettingsTab {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
Layout.topMargin: 15
|
||||
color: theme.grayRed900
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "Embedding"
|
||||
text: qsTr("Embedding")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.bottomMargin: 15
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: theme.grayRed500
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
MySettingsLabel {
|
||||
text: qsTr("Use Nomic Embed API")
|
||||
helpText: qsTr("Embed documents using the fast Nomic API instead of a private local model.")
|
||||
helpText: qsTr("Embed documents using the fast Nomic API instead of a private local model. Requires restart.")
|
||||
}
|
||||
|
||||
MyCheckBox {
|
||||
@ -113,11 +124,45 @@ MySettingsTab {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
MySettingsLabel {
|
||||
id: deviceLabel
|
||||
text: qsTr("Embeddings Device")
|
||||
helpText: qsTr('The compute device used for embeddings. "Auto" uses the CPU. Requires restart.')
|
||||
}
|
||||
MyComboBox {
|
||||
id: deviceBox
|
||||
enabled: !useNomicAPIBox.checked
|
||||
Layout.minimumWidth: 400
|
||||
Layout.maximumWidth: 400
|
||||
Layout.fillWidth: false
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: MySettings.embeddingsDeviceList
|
||||
Accessible.name: deviceLabel.text
|
||||
Accessible.description: deviceLabel.helpText
|
||||
function updateModel() {
|
||||
deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.localDocsEmbedDevice);
|
||||
}
|
||||
Component.onCompleted: {
|
||||
deviceBox.updateModel();
|
||||
}
|
||||
Connections {
|
||||
target: MySettings
|
||||
function onDeviceChanged() {
|
||||
deviceBox.updateModel();
|
||||
}
|
||||
}
|
||||
onActivated: {
|
||||
MySettings.localDocsEmbedDevice = deviceBox.currentText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
MySettingsLabel {
|
||||
id: apiKeyLabel
|
||||
text: qsTr("Nomic API Key")
|
||||
helpText: qsTr('API key to use for Nomic Embed. Get one from the Atlas <a href="https://atlas.nomic.ai/cli-login">API keys page</a>.')
|
||||
helpText: qsTr('API key to use for Nomic Embed. Get one from the Atlas <a href="https://atlas.nomic.ai/cli-login">API keys page</a>. Requires restart.')
|
||||
onLinkActivated: function(link) { Qt.openUrlExternally(link) }
|
||||
}
|
||||
|
||||
@ -148,26 +193,27 @@ MySettingsTab {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
Layout.topMargin: 15
|
||||
color: theme.grayRed900
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "Display"
|
||||
text: qsTr("Display")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.bottomMargin: 15
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: theme.grayRed500
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
MySettingsLabel {
|
||||
id: showReferencesLabel
|
||||
text: qsTr("Show sources")
|
||||
helpText: qsTr("Shows sources in GUI generated by localdocs")
|
||||
text: qsTr("Show Sources")
|
||||
helpText: qsTr("Display the sources used for each response.")
|
||||
}
|
||||
MyCheckBox {
|
||||
id: showReferencesBox
|
||||
@ -178,20 +224,21 @@ MySettingsTab {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
Layout.topMargin: 15
|
||||
color: theme.styledTextColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "Advanced"
|
||||
text: qsTr("Advanced")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.bottomMargin: 15
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: theme.settingsDivider
|
||||
}
|
||||
}
|
||||
|
||||
MySettingsLabel {
|
||||
id: warningLabel
|
||||
|
@ -307,7 +307,7 @@ Rectangle {
|
||||
}
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedDarkTextColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
Text {
|
||||
visible: {
|
||||
@ -322,7 +322,7 @@ Rectangle {
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedDarkTextColor
|
||||
font.family: "monospace"
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,21 +332,21 @@ Rectangle {
|
||||
text: "%1 – %2".arg(qsTr("%n file(s)", "", model.totalDocs)).arg(qsTr("%n word(s)", "", model.totalWords))
|
||||
elide: Text.ElideRight
|
||||
color: theme.styledTextColor2
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
Text {
|
||||
text: model.embeddingModel
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedDarkTextColor
|
||||
font.bold: true
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
Text {
|
||||
visible: Qt.formatDateTime(model.lastUpdate) !== ""
|
||||
text: Qt.formatDateTime(model.lastUpdate)
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedTextColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
Text {
|
||||
visible: model.currentEmbeddingsToIndex !== 0
|
||||
@ -354,7 +354,7 @@ Rectangle {
|
||||
+ model.totalEmbeddingsToIndex + " embeddings"
|
||||
elide: Text.ElideRight
|
||||
color: theme.mutedTextColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,53 +400,29 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
spacing: 30
|
||||
Layout.leftMargin: 15
|
||||
Layout.rightMargin: 15
|
||||
Layout.topMargin: 15
|
||||
Text {
|
||||
MyTextButton {
|
||||
text: qsTr("Remove")
|
||||
elide: Text.ElideRight
|
||||
color: theme.red500
|
||||
font.bold: true
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
LocalDocs.removeFolder(collection, folder_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
visible: !model.forceIndexing && !model.indexing && model.currentEmbeddingsToIndex === 0
|
||||
text: qsTr("Rebuild")
|
||||
elide: Text.ElideRight
|
||||
color: theme.red500
|
||||
font.bold: true
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
TapHandler {
|
||||
onTapped: { LocalDocs.forceRebuildFolder(folder_path); }
|
||||
}
|
||||
HoverHandler { id: hoverHandler1 }
|
||||
ToolTip.text: qsTr("Reindex this folder from scratch. This is slow and usually not needed.")
|
||||
ToolTip.visible: hoverHandler1.hovered
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
onClick: LocalDocs.removeFolder(collection, folder_path)
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
MyTextButton {
|
||||
visible: !model.forceIndexing && !model.indexing && model.currentEmbeddingsToIndex === 0
|
||||
text: qsTr("Rebuild")
|
||||
color: theme.green500
|
||||
onClick: { LocalDocs.forceRebuildFolder(folder_path); }
|
||||
tooltip: qsTr("Reindex this folder from scratch. This is slow and usually not needed.")
|
||||
}
|
||||
MyTextButton {
|
||||
visible: model.forceIndexing
|
||||
text: qsTr("Update")
|
||||
elide: Text.ElideRight
|
||||
color: theme.red500
|
||||
font.bold: true
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
TapHandler {
|
||||
onTapped: { LocalDocs.forceIndexing(collection); }
|
||||
}
|
||||
HoverHandler { id: hoverHandler2 }
|
||||
ToolTip.text: qsTr("Update the collection to the new version. This is a slow operation.")
|
||||
ToolTip.visible: hoverHandler2.hovered
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
color: theme.green500
|
||||
onClick: { LocalDocs.forceIndexing(collection); }
|
||||
tooltip: qsTr("Update the collection to the new version. This is a slow operation.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ MySettingsTab {
|
||||
onRestoreDefaultsClicked: {
|
||||
MySettings.restoreModelDefaults(root.currentModelInfo);
|
||||
}
|
||||
title: qsTr("Model/Character Settings")
|
||||
title: qsTr("Model")
|
||||
contentItem: GridLayout {
|
||||
id: root
|
||||
columns: 3
|
||||
@ -23,32 +23,14 @@ MySettingsTab {
|
||||
property var currentModelId: comboBox.currentValue
|
||||
property var currentModelInfo: ModelList.modelInfo(root.currentModelId)
|
||||
|
||||
ColumnLayout {
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 3
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
Label {
|
||||
color: theme.styledTextColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
text: "General"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 1
|
||||
color: theme.settingsDivider
|
||||
}
|
||||
}
|
||||
|
||||
MySettingsLabel {
|
||||
id: label
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
text: qsTr("Model/Character")
|
||||
helpText: qsTr("Select or clone a model and change its settings")
|
||||
Layout.bottomMargin: 10
|
||||
color: theme.settingsTitleTextColor
|
||||
font.pixelSize: theme.fontSizeBannerSmall
|
||||
font.bold: true
|
||||
text: qsTr("Model Settings")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
@ -56,7 +38,6 @@ MySettingsTab {
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 2
|
||||
height: label.height + 20
|
||||
spacing: 10
|
||||
|
||||
MyComboBox {
|
||||
@ -122,9 +103,7 @@ MySettingsTab {
|
||||
Layout.topMargin: 15
|
||||
spacing: 10
|
||||
MySettingsLabel {
|
||||
id: uniqueNameLabel
|
||||
text: qsTr("Unique Name")
|
||||
helpText: qsTr("Must contain a non-empty unique name")
|
||||
text: qsTr("Name")
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +137,6 @@ MySettingsTab {
|
||||
|
||||
MySettingsLabel {
|
||||
text: qsTr("Model File")
|
||||
helpText: qsTr("The filename of the selected model")
|
||||
Layout.row: 5
|
||||
Layout.column: 0
|
||||
Layout.topMargin: 15
|
||||
@ -177,7 +155,7 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("System Prompt")
|
||||
helpText: qsTr("Prefixed at the beginning of every conversation")
|
||||
helpText: qsTr("Prefixed at the beginning of every conversation. Must contain the appropriate framing tokens.")
|
||||
Layout.row: 7
|
||||
Layout.column: 0
|
||||
Layout.topMargin: 15
|
||||
@ -212,9 +190,6 @@ MySettingsTab {
|
||||
MySettings.setModelSystemPrompt(root.currentModelInfo, text)
|
||||
}
|
||||
Accessible.role: Accessible.EditableText
|
||||
ToolTip.text: qsTr("The systemPrompt allows instructions to the model at the beginning of a chat.\nNOTE: A longer, detailed system prompt can lead to higher quality answers, but can also slow down generation.")
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +202,7 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: promptTemplateLabel
|
||||
text: qsTr("Prompt Template")
|
||||
helpText: qsTr("The template that wraps every prompt")
|
||||
helpText: qsTr("The template that wraps every prompt.")
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: promptTemplateLabelHelp
|
||||
@ -271,9 +246,6 @@ MySettingsTab {
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: promptTemplateLabel.text
|
||||
Accessible.description: promptTemplateLabelHelp.text
|
||||
ToolTip.text: qsTr("The prompt template partially determines how models will respond to prompts.\nNOTE: A longer, detailed template can lead to higher quality answers, but can also slow down generation.")
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +300,7 @@ MySettingsTab {
|
||||
id: contextLengthLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Context Length")
|
||||
helpText: qsTr("Conversation context window")
|
||||
helpText: qsTr("Number of input and output tokens the model sees.")
|
||||
Layout.row: 0
|
||||
Layout.column: 0
|
||||
}
|
||||
@ -378,7 +350,7 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: tempLabel
|
||||
text: qsTr("Temperature")
|
||||
helpText: qsTr("The temperature for model token generation")
|
||||
helpText: qsTr("Randomness of model output. Higher -> more variation.")
|
||||
Layout.row: 1
|
||||
Layout.column: 2
|
||||
}
|
||||
@ -422,8 +394,8 @@ MySettingsTab {
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: topPLabel
|
||||
text: qsTr("Top P")
|
||||
helpText: qsTr("Prevents choosing highly unlikely tokens")
|
||||
text: qsTr("Top-P")
|
||||
helpText: qsTr("Nucleus Sampling factor. Lower -> more predicatable.")
|
||||
Layout.row: 2
|
||||
Layout.column: 0
|
||||
}
|
||||
@ -432,7 +404,7 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.topP
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens, aka Nucleus Sampling")
|
||||
ToolTip.text: qsTr("Only the most likely tokens up to a total probability of top_p can be chosen.\nNOTE: Prevents choosing highly unlikely tokens.")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 2
|
||||
Layout.column: 1
|
||||
@ -466,8 +438,8 @@ MySettingsTab {
|
||||
}
|
||||
MySettingsLabel {
|
||||
id: minPLabel
|
||||
text: qsTr("Min P")
|
||||
helpText: qsTr("Minimum relative probability")
|
||||
text: qsTr("Min-P")
|
||||
helpText: qsTr("Minimum token probability. Higher -> more predictable.")
|
||||
Layout.row: 3
|
||||
Layout.column: 0
|
||||
}
|
||||
@ -512,8 +484,8 @@ MySettingsTab {
|
||||
MySettingsLabel {
|
||||
id: topKLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Top K")
|
||||
helpText: qsTr("Size of selection pool for tokens")
|
||||
text: qsTr("Top-K")
|
||||
helpText: qsTr("Size of selection pool for tokens.")
|
||||
Layout.row: 2
|
||||
Layout.column: 2
|
||||
}
|
||||
@ -523,7 +495,7 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.topK
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from")
|
||||
ToolTip.text: qsTr("Only the top K most likely tokens will be chosen from.")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 2
|
||||
Layout.column: 3
|
||||
@ -559,7 +531,7 @@ MySettingsTab {
|
||||
id: maxLengthLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Max Length")
|
||||
helpText: qsTr("Maximum length of response in tokens")
|
||||
helpText: qsTr("Maximum response length, in tokens.")
|
||||
Layout.row: 0
|
||||
Layout.column: 2
|
||||
}
|
||||
@ -569,8 +541,6 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.maxLength
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Maximum length of response in tokens")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 0
|
||||
Layout.column: 3
|
||||
validator: IntValidator {
|
||||
@ -606,7 +576,7 @@ MySettingsTab {
|
||||
id: batchSizeLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Prompt Batch Size")
|
||||
helpText: qsTr("Amount of prompt tokens to process at once")
|
||||
helpText: qsTr("The batch size used for prompt processing.")
|
||||
Layout.row: 1
|
||||
Layout.column: 0
|
||||
}
|
||||
@ -616,7 +586,7 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.promptBatchSize
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM")
|
||||
ToolTip.text: qsTr("Amount of prompt tokens to process at once.\nNOTE: Higher values can speed up reading prompts but will use more RAM.")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 1
|
||||
Layout.column: 1
|
||||
@ -652,7 +622,7 @@ MySettingsTab {
|
||||
id: repeatPenaltyLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Repeat Penalty")
|
||||
helpText: qsTr("Penalize repetitiveness")
|
||||
helpText: qsTr("Repetition penalty factor. Set to 1 to disable.")
|
||||
Layout.row: 4
|
||||
Layout.column: 2
|
||||
}
|
||||
@ -662,8 +632,6 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.repeatPenalty
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("Amount to penalize repetitiveness of the output")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 4
|
||||
Layout.column: 3
|
||||
validator: DoubleValidator {
|
||||
@ -698,7 +666,7 @@ MySettingsTab {
|
||||
id: repeatPenaltyTokensLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("Repeat Penalty Tokens")
|
||||
helpText: qsTr("Length to apply penalty")
|
||||
helpText: qsTr("Number of previous tokens used for penalty.")
|
||||
Layout.row: 3
|
||||
Layout.column: 2
|
||||
}
|
||||
@ -708,8 +676,6 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.repeatPenaltyTokens
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
ToolTip.text: qsTr("How far back in output to apply repeat penalty")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 3
|
||||
Layout.column: 3
|
||||
validator: IntValidator {
|
||||
@ -745,7 +711,7 @@ MySettingsTab {
|
||||
id: gpuLayersLabel
|
||||
visible: !root.currentModelInfo.isOnline
|
||||
text: qsTr("GPU Layers")
|
||||
helpText: qsTr("How many GPU layers to load into VRAM")
|
||||
helpText: qsTr("Number of model layers to load into VRAM.")
|
||||
Layout.row: 4
|
||||
Layout.column: 0
|
||||
}
|
||||
@ -755,7 +721,7 @@ MySettingsTab {
|
||||
text: root.currentModelInfo.gpuLayers
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
color: theme.textColor
|
||||
ToolTip.text: qsTr("How many GPU layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
|
||||
ToolTip.text: qsTr("How many model layers to load into VRAM. Decrease this if GPT4All runs out of VRAM while loading this model.\nLower values increase CPU load and RAM usage, and make inference slower.\nNOTE: Does not take effect until you reload the model.")
|
||||
ToolTip.visible: hovered
|
||||
Layout.row: 4
|
||||
Layout.column: 1
|
||||
|
@ -180,13 +180,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("File size")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: filesize
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -202,13 +202,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("RAM required")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: ramrequired + qsTr(" GB")
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -224,13 +224,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Parameters")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: parameters
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -246,13 +246,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Quant")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: quant
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
@ -268,13 +268,13 @@ Rectangle {
|
||||
Layout.rightMargin: 20
|
||||
Text {
|
||||
text: qsTr("Type")
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: type
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ ColumnLayout {
|
||||
Label {
|
||||
id: mainTextLabel
|
||||
color: theme.settingsTitleTextColor
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
font.bold: true
|
||||
onLinkActivated: function(link) {
|
||||
root.linkActivated(link);
|
||||
@ -28,12 +28,13 @@ ColumnLayout {
|
||||
}
|
||||
Label {
|
||||
id: helpTextLabel
|
||||
visible: text !== ""
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
color: theme.settingsTitleTextColor
|
||||
text: mainTextLabel.text
|
||||
font.pixelSize: theme.fontSizeSmaller
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: false
|
||||
|
||||
onLinkActivated: function(link) {
|
||||
root.linkActivated(link);
|
||||
}
|
||||
|
19
gpt4all-chat/qml/MyTextButton.qml
Normal file
19
gpt4all-chat/qml/MyTextButton.qml
Normal file
@ -0,0 +1,19 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Text {
|
||||
id: text
|
||||
|
||||
signal click()
|
||||
property string tooltip
|
||||
|
||||
HoverHandler { id: hoverHandler }
|
||||
TapHandler { onTapped: { click() } }
|
||||
|
||||
font.bold: true
|
||||
font.underline: hoverHandler.hovered
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
ToolTip.text: tooltip
|
||||
ToolTip.visible: tooltip !== "" && hoverHandler.hovered
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
}
|
@ -33,7 +33,7 @@ Button {
|
||||
visible: myButton.toggled
|
||||
border.color: myButton.toggledColor
|
||||
border.width: myButton.toggledWidth
|
||||
radius: 10
|
||||
radius: 8
|
||||
}
|
||||
Image {
|
||||
id: image
|
||||
|
@ -1058,19 +1058,17 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
property real fontSizeLargeCapped: MySettings.fontSize === "Small" ? 12 : 17
|
||||
property real fontScale: MySettings.fontSize === "Small" ? 1 :
|
||||
MySettings.fontSize === "Medium" ? 1.3 :
|
||||
/* "Large" */ 1.8
|
||||
|
||||
property real fontSizeLarge: MySettings.fontSize === "Small" ? 12 :
|
||||
MySettings.fontSize === "Medium" ? 17 :
|
||||
22
|
||||
|
||||
property real fontSizeLargest: MySettings.fontSize === "Small" ? 19 :
|
||||
MySettings.fontSize === "Medium" ? 24 :
|
||||
26
|
||||
|
||||
property real fontSizeSmaller: fontSizeLarge - 4
|
||||
property real fontSizeSmall: fontSizeLarge - 2
|
||||
property real fontSizeLarger: fontSizeLarge + 2
|
||||
property real fontSizeBannerSmall: fontSizeLargest + 10
|
||||
property real fontSizeBanner: fontSizeLargest + 40
|
||||
property real fontSizeSmallest: 8 * fontScale
|
||||
property real fontSizeSmaller: 9 * fontScale
|
||||
property real fontSizeSmall: 10 * fontScale
|
||||
property real fontSizeMedium: 11 * fontScale
|
||||
property real fontSizeLarge: 12 * fontScale
|
||||
property real fontSizeLarger: 14 * fontScale
|
||||
property real fontSizeLargest: 18 * fontScale
|
||||
property real fontSizeBannerSmall: 24 * fontScale**.8
|
||||
property real fontSizeBanner: 48 * fontScale**.8
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user