mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-07-20 18:19:49 +00:00
modellist: refactor some lambdas into functions
Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
parent
d098426e0c
commit
f6c8c7cb90
@ -1210,132 +1210,133 @@ bool ModelList::modelExists(const QString &modelFilename) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateOldRemoteModels(const QString &path)
|
||||||
|
{
|
||||||
|
QDirIterator it(path, QDirIterator::Subdirectories);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
if (!it.fileInfo().isDir()) {
|
||||||
|
QString filename = it.fileName();
|
||||||
|
if (filename.startsWith("chatgpt-") && filename.endsWith(".txt")) {
|
||||||
|
QString apikey;
|
||||||
|
QString modelname(filename);
|
||||||
|
modelname.chop(4); // strip ".txt" extension
|
||||||
|
modelname.remove(0, 8); // strip "chatgpt-" prefix
|
||||||
|
QFile file(path + filename);
|
||||||
|
if (file.open(QIODevice::ReadWrite)) {
|
||||||
|
QTextStream in(&file);
|
||||||
|
apikey = in.readAll();
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject obj;
|
||||||
|
obj.insert("apiKey", apikey);
|
||||||
|
obj.insert("modelName", modelname);
|
||||||
|
QJsonDocument doc(obj);
|
||||||
|
|
||||||
|
auto newfilename = u"gpt4all-%1.rmodel"_s.arg(modelname);
|
||||||
|
QFile newfile(path + newfilename);
|
||||||
|
if (newfile.open(QIODevice::ReadWrite)) {
|
||||||
|
QTextStream out(&newfile);
|
||||||
|
out << doc.toJson();
|
||||||
|
newfile.close();
|
||||||
|
}
|
||||||
|
file.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelList::processModelDirectory(const QString &path)
|
||||||
|
{
|
||||||
|
QDirIterator it(path, QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
|
||||||
|
QString filename = it.fileName();
|
||||||
|
if (filename.startsWith("incomplete") || FILENAME_BLACKLIST.contains(filename))
|
||||||
|
continue;
|
||||||
|
if (!filename.endsWith(".gguf") && !filename.endsWith(".rmodel"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QVector<QString> modelsById;
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
for (ModelInfo *info : m_models)
|
||||||
|
if (info->filename() == filename)
|
||||||
|
modelsById.append(info->id());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelsById.isEmpty()) {
|
||||||
|
if (!contains(filename))
|
||||||
|
addModel(filename);
|
||||||
|
modelsById.append(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo info = it.fileInfo();
|
||||||
|
|
||||||
|
bool isOnline(filename.endsWith(".rmodel"));
|
||||||
|
bool isCompatibleApi(filename.endsWith("-capi.rmodel"));
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
QString description;
|
||||||
|
if (isCompatibleApi) {
|
||||||
|
QJsonObject obj;
|
||||||
|
{
|
||||||
|
QFile file(path + filename);
|
||||||
|
bool success = file.open(QIODeviceBase::ReadOnly);
|
||||||
|
(void)success;
|
||||||
|
Q_ASSERT(success);
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
||||||
|
obj = doc.object();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QString apiKey(obj["apiKey"].toString());
|
||||||
|
QString baseUrl(obj["baseUrl"].toString());
|
||||||
|
QString modelName(obj["modelName"].toString());
|
||||||
|
apiKey = apiKey.length() < 10 ? "*****" : apiKey.left(5) + "*****";
|
||||||
|
name = tr("%1 (%2)").arg(modelName, baseUrl);
|
||||||
|
description = tr("<strong>OpenAI-Compatible API Model</strong><br>"
|
||||||
|
"<ul><li>API Key: %1</li>"
|
||||||
|
"<li>Base URL: %2</li>"
|
||||||
|
"<li>Model Name: %3</li></ul>")
|
||||||
|
.arg(apiKey, baseUrl, modelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QString &id : modelsById) {
|
||||||
|
QVector<QPair<int, QVariant>> data {
|
||||||
|
{ InstalledRole, true },
|
||||||
|
{ FilenameRole, filename },
|
||||||
|
{ OnlineRole, isOnline },
|
||||||
|
{ CompatibleApiRole, isCompatibleApi },
|
||||||
|
{ DirpathRole, info.dir().absolutePath() + "/" },
|
||||||
|
{ FilesizeRole, info.size() },
|
||||||
|
};
|
||||||
|
if (isCompatibleApi) {
|
||||||
|
// The data will be saved to "GPT4All.ini".
|
||||||
|
data.append({ NameRole, name });
|
||||||
|
// The description is hard-coded into "GPT4All.ini" due to performance issue.
|
||||||
|
// If the description goes to be dynamic from its .rmodel file, it will get high I/O usage while using the ModelList.
|
||||||
|
data.append({ DescriptionRole, description });
|
||||||
|
// Prompt template should be clear while using ChatML format which is using in most of OpenAI-Compatible API server.
|
||||||
|
data.append({ PromptTemplateRole, "%1" });
|
||||||
|
}
|
||||||
|
updateData(id, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ModelList::updateModelsFromDirectory()
|
void ModelList::updateModelsFromDirectory()
|
||||||
{
|
{
|
||||||
const QString exePath = QCoreApplication::applicationDirPath() + QDir::separator();
|
const QString exePath = QCoreApplication::applicationDirPath() + QDir::separator();
|
||||||
const QString localPath = MySettings::globalInstance()->modelPath();
|
const QString localPath = MySettings::globalInstance()->modelPath();
|
||||||
|
|
||||||
auto updateOldRemoteModels = [&](const QString& path) {
|
|
||||||
QDirIterator it(path, QDirIterator::Subdirectories);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
if (!it.fileInfo().isDir()) {
|
|
||||||
QString filename = it.fileName();
|
|
||||||
if (filename.startsWith("chatgpt-") && filename.endsWith(".txt")) {
|
|
||||||
QString apikey;
|
|
||||||
QString modelname(filename);
|
|
||||||
modelname.chop(4); // strip ".txt" extension
|
|
||||||
modelname.remove(0, 8); // strip "chatgpt-" prefix
|
|
||||||
QFile file(path + filename);
|
|
||||||
if (file.open(QIODevice::ReadWrite)) {
|
|
||||||
QTextStream in(&file);
|
|
||||||
apikey = in.readAll();
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject obj;
|
|
||||||
obj.insert("apiKey", apikey);
|
|
||||||
obj.insert("modelName", modelname);
|
|
||||||
QJsonDocument doc(obj);
|
|
||||||
|
|
||||||
auto newfilename = u"gpt4all-%1.rmodel"_s.arg(modelname);
|
|
||||||
QFile newfile(path + newfilename);
|
|
||||||
if (newfile.open(QIODevice::ReadWrite)) {
|
|
||||||
QTextStream out(&newfile);
|
|
||||||
out << doc.toJson();
|
|
||||||
newfile.close();
|
|
||||||
}
|
|
||||||
file.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto processDirectory = [&](const QString& path) {
|
|
||||||
QDirIterator it(path, QDir::Files, QDirIterator::Subdirectories);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
|
|
||||||
QString filename = it.fileName();
|
|
||||||
if (filename.startsWith("incomplete") || FILENAME_BLACKLIST.contains(filename))
|
|
||||||
continue;
|
|
||||||
if (!filename.endsWith(".gguf") && !filename.endsWith(".rmodel"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QVector<QString> modelsById;
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
for (ModelInfo *info : m_models)
|
|
||||||
if (info->filename() == filename)
|
|
||||||
modelsById.append(info->id());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modelsById.isEmpty()) {
|
|
||||||
if (!contains(filename))
|
|
||||||
addModel(filename);
|
|
||||||
modelsById.append(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFileInfo info = it.fileInfo();
|
|
||||||
|
|
||||||
bool isOnline(filename.endsWith(".rmodel"));
|
|
||||||
bool isCompatibleApi(filename.endsWith("-capi.rmodel"));
|
|
||||||
|
|
||||||
QString name;
|
|
||||||
QString description;
|
|
||||||
if (isCompatibleApi) {
|
|
||||||
QJsonObject obj;
|
|
||||||
{
|
|
||||||
QFile file(path + filename);
|
|
||||||
bool success = file.open(QIODeviceBase::ReadOnly);
|
|
||||||
(void)success;
|
|
||||||
Q_ASSERT(success);
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
|
||||||
obj = doc.object();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
QString apiKey(obj["apiKey"].toString());
|
|
||||||
QString baseUrl(obj["baseUrl"].toString());
|
|
||||||
QString modelName(obj["modelName"].toString());
|
|
||||||
apiKey = apiKey.length() < 10 ? "*****" : apiKey.left(5) + "*****";
|
|
||||||
name = tr("%1 (%2)").arg(modelName, baseUrl);
|
|
||||||
description = tr("<strong>OpenAI-Compatible API Model</strong><br>"
|
|
||||||
"<ul><li>API Key: %1</li>"
|
|
||||||
"<li>Base URL: %2</li>"
|
|
||||||
"<li>Model Name: %3</li></ul>")
|
|
||||||
.arg(apiKey, baseUrl, modelName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const QString &id : modelsById) {
|
|
||||||
QVector<QPair<int, QVariant>> data {
|
|
||||||
{ InstalledRole, true },
|
|
||||||
{ FilenameRole, filename },
|
|
||||||
{ OnlineRole, isOnline },
|
|
||||||
{ CompatibleApiRole, isCompatibleApi },
|
|
||||||
{ DirpathRole, info.dir().absolutePath() + "/" },
|
|
||||||
{ FilesizeRole, info.size() },
|
|
||||||
};
|
|
||||||
if (isCompatibleApi) {
|
|
||||||
// The data will be saved to "GPT4All.ini".
|
|
||||||
data.append({ NameRole, name });
|
|
||||||
// The description is hard-coded into "GPT4All.ini" due to performance issue.
|
|
||||||
// If the description goes to be dynamic from its .rmodel file, it will get high I/O usage while using the ModelList.
|
|
||||||
data.append({ DescriptionRole, description });
|
|
||||||
// Prompt template should be clear while using ChatML format which is using in most of OpenAI-Compatible API server.
|
|
||||||
data.append({ PromptTemplateRole, "%1" });
|
|
||||||
}
|
|
||||||
updateData(id, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
updateOldRemoteModels(exePath);
|
updateOldRemoteModels(exePath);
|
||||||
processDirectory(exePath);
|
processModelDirectory(exePath);
|
||||||
if (localPath != exePath) {
|
if (localPath != exePath) {
|
||||||
updateOldRemoteModels(localPath);
|
updateOldRemoteModels(localPath);
|
||||||
processDirectory(localPath);
|
processModelDirectory(localPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +509,7 @@ private:
|
|||||||
void parseModelsJsonFile(const QByteArray &jsonData, bool save);
|
void parseModelsJsonFile(const QByteArray &jsonData, bool save);
|
||||||
void parseDiscoveryJsonFile(const QByteArray &jsonData);
|
void parseDiscoveryJsonFile(const QByteArray &jsonData);
|
||||||
QString uniqueModelName(const ModelInfo &model) const;
|
QString uniqueModelName(const ModelInfo &model) const;
|
||||||
|
void processModelDirectory(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable QMutex m_mutex;
|
mutable QMutex m_mutex;
|
||||||
|
Loading…
Reference in New Issue
Block a user