feat: Add support for Mistral API models (#2053)

Signed-off-by: Jared Van Bortel <jared@nomic.ai>
Signed-off-by: Cédric Sazos <cedric.sazos@tutanota.com>
Co-authored-by: Jared Van Bortel <jared@nomic.ai>
pull/2119/head
Olyxz16 3 months ago committed by GitHub
parent 406e88b59a
commit 2c0a660e6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -73,7 +73,7 @@ qt_add_executable(chat
chat.h chat.cpp
chatllm.h chatllm.cpp
chatmodel.h chatlistmodel.h chatlistmodel.cpp
chatgpt.h chatgpt.cpp
chatapi.h chatapi.cpp
database.h database.cpp
embeddings.h embeddings.cpp
download.h download.cpp

@ -1,4 +1,4 @@
#include "chatgpt.h"
#include "chatapi.h"
#include <string>
#include <vector>
@ -13,14 +13,15 @@
//#define DEBUG
ChatGPT::ChatGPT()
ChatAPI::ChatAPI()
: QObject(nullptr)
, m_modelName("gpt-3.5-turbo")
, m_requestURL("")
, m_responseCallback(nullptr)
{
}
size_t ChatGPT::requiredMem(const std::string &modelPath, int n_ctx, int ngl)
size_t ChatAPI::requiredMem(const std::string &modelPath, int n_ctx, int ngl)
{
Q_UNUSED(modelPath);
Q_UNUSED(n_ctx);
@ -28,7 +29,7 @@ size_t ChatGPT::requiredMem(const std::string &modelPath, int n_ctx, int ngl)
return 0;
}
bool ChatGPT::loadModel(const std::string &modelPath, int n_ctx, int ngl)
bool ChatAPI::loadModel(const std::string &modelPath, int n_ctx, int ngl)
{
Q_UNUSED(modelPath);
Q_UNUSED(n_ctx);
@ -36,59 +37,59 @@ bool ChatGPT::loadModel(const std::string &modelPath, int n_ctx, int ngl)
return true;
}
void ChatGPT::setThreadCount(int32_t n_threads)
void ChatAPI::setThreadCount(int32_t n_threads)
{
Q_UNUSED(n_threads);
qt_noop();
}
int32_t ChatGPT::threadCount() const
int32_t ChatAPI::threadCount() const
{
return 1;
}
ChatGPT::~ChatGPT()
ChatAPI::~ChatAPI()
{
}
bool ChatGPT::isModelLoaded() const
bool ChatAPI::isModelLoaded() const
{
return true;
}
// All three of the state virtual functions are handled custom inside of chatllm save/restore
size_t ChatGPT::stateSize() const
size_t ChatAPI::stateSize() const
{
return 0;
}
size_t ChatGPT::saveState(uint8_t *dest) const
size_t ChatAPI::saveState(uint8_t *dest) const
{
Q_UNUSED(dest);
return 0;
}
size_t ChatGPT::restoreState(const uint8_t *src)
size_t ChatAPI::restoreState(const uint8_t *src)
{
Q_UNUSED(src);
return 0;
}
void ChatGPT::prompt(const std::string &prompt,
const std::string &promptTemplate,
std::function<bool(int32_t)> promptCallback,
std::function<bool(int32_t, const std::string&)> responseCallback,
std::function<bool(bool)> recalculateCallback,
PromptContext &promptCtx,
bool special,
std::string *fakeReply) {
void ChatAPI::prompt(const std::string &prompt,
const std::string &promptTemplate,
std::function<bool(int32_t)> promptCallback,
std::function<bool(int32_t, const std::string&)> responseCallback,
std::function<bool(bool)> recalculateCallback,
PromptContext &promptCtx,
bool special,
std::string *fakeReply) {
Q_UNUSED(promptCallback);
Q_UNUSED(recalculateCallback);
Q_UNUSED(special);
if (!isModelLoaded()) {
std::cerr << "ChatGPT ERROR: prompt won't work with an unloaded model!\n";
std::cerr << "ChatAPI ERROR: prompt won't work with an unloaded model!\n";
return;
}
@ -128,7 +129,7 @@ void ChatGPT::prompt(const std::string &prompt,
QJsonArray messages;
for (int i = 0; i < m_context.count(); ++i) {
QJsonObject message;
message.insert("role", i % 2 == 0 ? "assistant" : "user");
message.insert("role", i % 2 == 0 ? "user" : "assistant");
message.insert("content", m_context.at(i));
messages.append(message);
}
@ -142,7 +143,7 @@ void ChatGPT::prompt(const std::string &prompt,
QJsonDocument doc(root);
#if defined(DEBUG)
qDebug().noquote() << "ChatGPT::prompt begin network request" << doc.toJson();
qDebug().noquote() << "ChatAPI::prompt begin network request" << doc.toJson();
#endif
m_responseCallback = responseCallback;
@ -150,10 +151,10 @@ void ChatGPT::prompt(const std::string &prompt,
// The following code sets up a worker thread and object to perform the actual api request to
// chatgpt and then blocks until it is finished
QThread workerThread;
ChatGPTWorker worker(this);
ChatAPIWorker worker(this);
worker.moveToThread(&workerThread);
connect(&worker, &ChatGPTWorker::finished, &workerThread, &QThread::quit, Qt::DirectConnection);
connect(this, &ChatGPT::request, &worker, &ChatGPTWorker::request, Qt::QueuedConnection);
connect(&worker, &ChatAPIWorker::finished, &workerThread, &QThread::quit, Qt::DirectConnection);
connect(this, &ChatAPI::request, &worker, &ChatAPIWorker::request, Qt::QueuedConnection);
workerThread.start();
emit request(m_apiKey, &promptCtx, doc.toJson(QJsonDocument::Compact));
workerThread.wait();
@ -164,40 +165,40 @@ void ChatGPT::prompt(const std::string &prompt,
m_responseCallback = nullptr;
#if defined(DEBUG)
qDebug() << "ChatGPT::prompt end network request";
qDebug() << "ChatAPI::prompt end network request";
#endif
}
bool ChatGPT::callResponse(int32_t token, const std::string& string)
bool ChatAPI::callResponse(int32_t token, const std::string& string)
{
Q_ASSERT(m_responseCallback);
if (!m_responseCallback) {
std::cerr << "ChatGPT ERROR: no response callback!\n";
std::cerr << "ChatAPI ERROR: no response callback!\n";
return false;
}
return m_responseCallback(token, string);
}
void ChatGPTWorker::request(const QString &apiKey,
LLModel::PromptContext *promptCtx,
const QByteArray &array)
void ChatAPIWorker::request(const QString &apiKey,
LLModel::PromptContext *promptCtx,
const QByteArray &array)
{
m_ctx = promptCtx;
QUrl openaiUrl("https://api.openai.com/v1/chat/completions");
QUrl apiUrl(m_chat->url());
const QString authorization = QString("Bearer %1").arg(apiKey).trimmed();
QNetworkRequest request(openaiUrl);
QNetworkRequest request(apiUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", authorization.toUtf8());
m_networkManager = new QNetworkAccessManager(this);
QNetworkReply *reply = m_networkManager->post(request, array);
connect(qApp, &QCoreApplication::aboutToQuit, reply, &QNetworkReply::abort);
connect(reply, &QNetworkReply::finished, this, &ChatGPTWorker::handleFinished);
connect(reply, &QNetworkReply::readyRead, this, &ChatGPTWorker::handleReadyRead);
connect(reply, &QNetworkReply::errorOccurred, this, &ChatGPTWorker::handleErrorOccurred);
connect(reply, &QNetworkReply::finished, this, &ChatAPIWorker::handleFinished);
connect(reply, &QNetworkReply::readyRead, this, &ChatAPIWorker::handleReadyRead);
connect(reply, &QNetworkReply::errorOccurred, this, &ChatAPIWorker::handleErrorOccurred);
}
void ChatGPTWorker::handleFinished()
void ChatAPIWorker::handleFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (!reply) {
@ -210,14 +211,14 @@ void ChatGPTWorker::handleFinished()
bool ok;
int code = response.toInt(&ok);
if (!ok || code != 200) {
qWarning() << QString("ERROR: ChatGPT responded with error code \"%1-%2\"")
.arg(code).arg(reply->errorString());
qWarning().noquote() << "ERROR: ChatAPIWorker::handleFinished got HTTP Error" << code << "response:"
<< reply->errorString();
}
reply->deleteLater();
emit finished();
}
void ChatGPTWorker::handleReadyRead()
void ChatAPIWorker::handleReadyRead()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (!reply) {
@ -230,8 +231,11 @@ void ChatGPTWorker::handleReadyRead()
bool ok;
int code = response.toInt(&ok);
if (!ok || code != 200) {
m_chat->callResponse(-1, QString("\nERROR: 2 ChatGPT responded with error code \"%1-%2\" %3\n")
.arg(code).arg(reply->errorString()).arg(reply->readAll()).toStdString());
m_chat->callResponse(
-1,
QString("ERROR: ChatAPIWorker::handleReadyRead got HTTP Error %1 %2: %3")
.arg(code).arg(reply->errorString()).arg(reply->readAll()).toStdString()
);
emit finished();
return;
}
@ -251,8 +255,8 @@ void ChatGPTWorker::handleReadyRead()
QJsonParseError err;
const QJsonDocument document = QJsonDocument::fromJson(jsonData.toUtf8(), &err);
if (err.error != QJsonParseError::NoError) {
m_chat->callResponse(-1, QString("\nERROR: ChatGPT responded with invalid json \"%1\"\n")
.arg(err.errorString()).toStdString());
m_chat->callResponse(-1, QString("ERROR: ChatAPI responded with invalid json \"%1\"")
.arg(err.errorString()).toStdString());
continue;
}
@ -271,7 +275,7 @@ void ChatGPTWorker::handleReadyRead()
}
}
void ChatGPTWorker::handleErrorOccurred(QNetworkReply::NetworkError code)
void ChatAPIWorker::handleErrorOccurred(QNetworkReply::NetworkError code)
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (!reply || reply->error() == QNetworkReply::OperationCanceledError /*when we call abort on purpose*/) {
@ -279,7 +283,7 @@ void ChatGPTWorker::handleErrorOccurred(QNetworkReply::NetworkError code)
return;
}
qWarning() << QString("ERROR: ChatGPT responded with error code \"%1-%2\"")
.arg(code).arg(reply->errorString());
qWarning().noquote() << "ERROR: ChatAPIWorker::handleErrorOccurred got HTTP Error" << code << "response:"
<< reply->errorString();
emit finished();
}

@ -1,5 +1,5 @@
#ifndef CHATGPT_H
#define CHATGPT_H
#ifndef CHATAPI_H
#define CHATAPI_H
#include <stdexcept>
@ -13,22 +13,22 @@
#include "../gpt4all-backend/llmodel.h"
class ChatGPT;
class ChatGPTWorker : public QObject {
class ChatAPI;
class ChatAPIWorker : public QObject {
Q_OBJECT
public:
ChatGPTWorker(ChatGPT *chatGPT)
ChatAPIWorker(ChatAPI *chatAPI)
: QObject(nullptr)
, m_ctx(nullptr)
, m_networkManager(nullptr)
, m_chat(chatGPT) {}
virtual ~ChatGPTWorker() {}
, m_chat(chatAPI) {}
virtual ~ChatAPIWorker() {}
QString currentResponse() const { return m_currentResponse; }
void request(const QString &apiKey,
LLModel::PromptContext *promptCtx,
const QByteArray &array);
LLModel::PromptContext *promptCtx,
const QByteArray &array);
Q_SIGNALS:
void finished();
@ -39,17 +39,17 @@ private Q_SLOTS:
void handleErrorOccurred(QNetworkReply::NetworkError code);
private:
ChatGPT *m_chat;
ChatAPI *m_chat;
LLModel::PromptContext *m_ctx;
QNetworkAccessManager *m_networkManager;
QString m_currentResponse;
};
class ChatGPT : public QObject, public LLModel {
class ChatAPI : public QObject, public LLModel {
Q_OBJECT
public:
ChatGPT();
virtual ~ChatGPT();
ChatAPI();
virtual ~ChatAPI();
bool supportsEmbedding() const override { return false; }
bool supportsCompletion() const override { return true; }
@ -60,19 +60,21 @@ public:
size_t saveState(uint8_t *dest) const override;
size_t restoreState(const uint8_t *src) override;
void prompt(const std::string &prompt,
const std::string &promptTemplate,
std::function<bool(int32_t)> promptCallback,
std::function<bool(int32_t, const std::string&)> responseCallback,
std::function<bool(bool)> recalculateCallback,
PromptContext &ctx,
bool special,
std::string *fakeReply) override;
const std::string &promptTemplate,
std::function<bool(int32_t)> promptCallback,
std::function<bool(int32_t, const std::string&)> responseCallback,
std::function<bool(bool)> recalculateCallback,
PromptContext &ctx,
bool special,
std::string *fakeReply) override;
void setThreadCount(int32_t n_threads) override;
int32_t threadCount() const override;
void setModelName(const QString &modelName) { m_modelName = modelName; }
void setAPIKey(const QString &apiKey) { m_apiKey = apiKey; }
void setRequestURL(const QString &requestURL) { m_requestURL = requestURL; }
QString url() const { return m_requestURL; }
QList<QString> context() const { return m_context; }
void setContext(const QList<QString> &context) { m_context = context; }
@ -81,8 +83,8 @@ public:
Q_SIGNALS:
void request(const QString &apiKey,
LLModel::PromptContext *ctx,
const QByteArray &array);
LLModel::PromptContext *ctx,
const QByteArray &array);
protected:
// We have to implement these as they are pure virtual in base class, but we don't actually use
@ -128,8 +130,9 @@ private:
std::function<bool(int32_t, const std::string&)> m_responseCallback;
QString m_modelName;
QString m_apiKey;
QString m_requestURL;
QList<QString> m_context;
QStringList m_queuedPrompts;
};
#endif // CHATGPT_H
#endif // CHATAPI_H

@ -1,6 +1,6 @@
#include "chatllm.h"
#include "chat.h"
#include "chatgpt.h"
#include "chatapi.h"
#include "localdocs.h"
#include "modellist.h"
#include "network.h"
@ -213,7 +213,6 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
if (isModelLoaded() && this->modelInfo() == modelInfo)
return true;
bool isChatGPT = modelInfo.isOnline; // right now only chatgpt is offered for online chat models...
QString filePath = modelInfo.dirpath + modelInfo.filename();
QFileInfo fileInfo(filePath);
@ -279,19 +278,23 @@ bool ChatLLM::loadModel(const ModelInfo &modelInfo)
m_llModelInfo.fileInfo = fileInfo;
if (fileInfo.exists()) {
if (isChatGPT) {
if (modelInfo.isOnline) {
QString apiKey;
QString chatGPTModel = fileInfo.completeBaseName().remove(0, 8); // remove the chatgpt- prefix
QString modelName;
{
QFile file(filePath);
file.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text);
QTextStream stream(&file);
apiKey = stream.readAll();
file.close();
QString text = stream.readAll();
QJsonDocument doc = QJsonDocument::fromJson(text.toUtf8());
QJsonObject obj = doc.object();
apiKey = obj["apiKey"].toString();
modelName = obj["modelName"].toString();
}
m_llModelType = LLModelType::CHATGPT_;
ChatGPT *model = new ChatGPT();
model->setModelName(chatGPTModel);
m_llModelType = LLModelType::API_;
ChatAPI *model = new ChatAPI();
model->setModelName(modelName);
model->setRequestURL(modelInfo.url());
model->setAPIKey(apiKey);
m_llModelInfo.model = model;
} else {
@ -468,7 +471,7 @@ void ChatLLM::regenerateResponse()
{
// ChatGPT uses a different semantic meaning for n_past than local models. For ChatGPT, the meaning
// of n_past is of the number of prompt/response pairs, rather than for total tokens.
if (m_llModelType == LLModelType::CHATGPT_)
if (m_llModelType == LLModelType::API_)
m_ctx.n_past -= 1;
else
m_ctx.n_past -= m_promptResponseTokens;
@ -958,12 +961,12 @@ void ChatLLM::saveState()
if (!isModelLoaded())
return;
if (m_llModelType == LLModelType::CHATGPT_) {
if (m_llModelType == LLModelType::API_) {
m_state.clear();
QDataStream stream(&m_state, QIODeviceBase::WriteOnly);
stream.setVersion(QDataStream::Qt_6_4);
ChatGPT *chatGPT = static_cast<ChatGPT*>(m_llModelInfo.model);
stream << chatGPT->context();
ChatAPI *chatAPI = static_cast<ChatAPI*>(m_llModelInfo.model);
stream << chatAPI->context();
return;
}
@ -980,13 +983,13 @@ void ChatLLM::restoreState()
if (!isModelLoaded())
return;
if (m_llModelType == LLModelType::CHATGPT_) {
if (m_llModelType == LLModelType::API_) {
QDataStream stream(&m_state, QIODeviceBase::ReadOnly);
stream.setVersion(QDataStream::Qt_6_4);
ChatGPT *chatGPT = static_cast<ChatGPT*>(m_llModelInfo.model);
ChatAPI *chatAPI = static_cast<ChatAPI*>(m_llModelInfo.model);
QList<QString> context;
stream >> context;
chatGPT->setContext(context);
chatAPI->setContext(context);
m_state.clear();
m_state.squeeze();
return;

@ -12,7 +12,7 @@
enum LLModelType {
GPTJ_,
LLAMA_,
CHATGPT_,
API_,
};
struct LLModelInfo {

@ -182,8 +182,17 @@ void Download::installModel(const QString &modelFile, const QString &apiKey)
QString filePath = MySettings::globalInstance()->modelPath() + modelFile;
QFile file(filePath);
if (file.open(QIODeviceBase::WriteOnly | QIODeviceBase::Text)) {
QJsonObject obj;
QString modelName(modelFile);
modelName.remove(0, 8); // strip "gpt4all-" prefix
modelName.chop(7); // strip ".rmodel" extension
obj.insert("apiKey", apiKey);
obj.insert("modelName", modelName);
QJsonDocument doc(obj);
QTextStream stream(&file);
stream << apiKey;
stream << doc.toJson();
file.close();
ModelList::globalInstance()->updateModelsFromDirectory();
}

@ -1172,6 +1172,44 @@ void ModelList::updateModelsFromDirectory()
const QString exePath = QCoreApplication::applicationDirPath() + QDir::separator();
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.endsWith(".txt")) {
QString apikey;
QString modelname(filename);
modelname.chop(4); // strip ".txt" extension
if (filename.startsWith("chatgpt-")) {
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 = QString("gpt4all-%1.rmodel").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, QDirIterator::Subdirectories);
while (it.hasNext()) {
@ -1180,8 +1218,7 @@ void ModelList::updateModelsFromDirectory()
if (!it.fileInfo().isDir()) {
QString filename = it.fileName();
if ((filename.endsWith(".gguf") && !filename.startsWith("incomplete"))
|| (filename.endsWith(".txt") && (filename.startsWith("chatgpt-") || filename.startsWith("nomic-")))) {
if ((filename.endsWith(".gguf") && !filename.startsWith("incomplete")) || filename.endsWith(".rmodel")) {
QString filePath = it.filePath();
QFileInfo info(filePath);
@ -1207,8 +1244,7 @@ void ModelList::updateModelsFromDirectory()
QVector<QPair<int, QVariant>> data {
{ InstalledRole, true },
{ FilenameRole, filename },
// FIXME: WE should change this to use a consistent filename for online models
{ OnlineRole, filename.startsWith("chatgpt-") || filename.startsWith("nomic-") },
{ OnlineRole, filename.endsWith(".rmodel") },
{ DirpathRole, info.dir().absolutePath() + "/" },
{ FilesizeRole, toFileSize(info.size()) },
};
@ -1219,9 +1255,13 @@ void ModelList::updateModelsFromDirectory()
}
};
updateOldRemoteModels(exePath);
processDirectory(exePath);
if (localPath != exePath)
if (localPath != exePath) {
updateOldRemoteModels(localPath);
processDirectory(localPath);
}
}
#define MODELS_VERSION 3
@ -1466,7 +1506,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{
const QString modelName = "ChatGPT-3.5 Turbo";
const QString id = modelName;
const QString modelFilename = "chatgpt-gpt-3.5-turbo.txt";
const QString modelFilename = "gpt4all-gpt-3.5-turbo.rmodel";
if (contains(modelFilename))
changeId(modelFilename, id);
if (!contains(id))
@ -1478,12 +1518,13 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>OpenAI's ChatGPT model GPT-3.5 Turbo</strong><br>") + chatGPTDesc },
{ ModelList::RequiresVersionRole, "2.4.2" },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "ca" },
{ ModelList::RamrequiredRole, 0 },
{ ModelList::ParametersRole, "?" },
{ ModelList::QuantRole, "NA" },
{ ModelList::TypeRole, "GPT" },
{ ModelList::UrlRole, "https://api.openai.com/v1/chat/completions"},
};
updateData(id, data);
}
@ -1493,7 +1534,7 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
const QString modelName = "ChatGPT-4";
const QString id = modelName;
const QString modelFilename = "chatgpt-gpt-4.txt";
const QString modelFilename = "gpt4all-gpt-4.rmodel";
if (contains(modelFilename))
changeId(modelFilename, id);
if (!contains(id))
@ -1505,16 +1546,100 @@ void ModelList::parseModelsJsonFile(const QByteArray &jsonData, bool save)
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>OpenAI's ChatGPT model GPT-4</strong><br>") + chatGPTDesc + chatGPT4Warn },
{ ModelList::RequiresVersionRole, "2.4.2" },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cb" },
{ ModelList::RamrequiredRole, 0 },
{ ModelList::ParametersRole, "?" },
{ ModelList::QuantRole, "NA" },
{ ModelList::TypeRole, "GPT" },
{ ModelList::UrlRole, "https://api.openai.com/v1/chat/completions"},
};
updateData(id, data);
}
const QString mistralDesc = tr("<ul><li>Requires personal Mistral API key.</li><li>WARNING: Will send"
" your chats to Mistral!</li><li>Your API key will be stored on disk</li><li>Will only be used"
" to communicate with Mistral</li><li>You can apply for an API key"
" <a href=\"https://console.mistral.ai/user/api-keys\">here</a>.</li>");
{
const QString modelName = "Mistral Tiny API";
const QString id = modelName;
const QString modelFilename = "gpt4all-mistral-tiny.rmodel";
if (contains(modelFilename))
changeId(modelFilename, id);
if (!contains(id))
addModel(id);
QVector<QPair<int, QVariant>> data {
{ ModelList::NameRole, modelName },
{ ModelList::FilenameRole, modelFilename },
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Tiny model</strong><br>") + mistralDesc },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cc" },
{ ModelList::RamrequiredRole, 0 },
{ ModelList::ParametersRole, "?" },
{ ModelList::QuantRole, "NA" },
{ ModelList::TypeRole, "Mistral" },
{ ModelList::UrlRole, "https://api.mistral.ai/v1/chat/completions"},
};
updateData(id, data);
}
{
const QString modelName = "Mistral Small API";
const QString id = modelName;
const QString modelFilename = "gpt4all-mistral-small.rmodel";
if (contains(modelFilename))
changeId(modelFilename, id);
if (!contains(id))
addModel(id);
QVector<QPair<int, QVariant>> data {
{ ModelList::NameRole, modelName },
{ ModelList::FilenameRole, modelFilename },
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Small model</strong><br>") + mistralDesc },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "cd" },
{ ModelList::RamrequiredRole, 0 },
{ ModelList::ParametersRole, "?" },
{ ModelList::QuantRole, "NA" },
{ ModelList::TypeRole, "Mistral" },
{ ModelList::UrlRole, "https://api.mistral.ai/v1/chat/completions"},
};
updateData(id, data);
}
{
const QString modelName = "Mistral Medium API";
const QString id = modelName;
const QString modelFilename = "gpt4all-mistral-medium.rmodel";
if (contains(modelFilename))
changeId(modelFilename, id);
if (!contains(id))
addModel(id);
QVector<QPair<int, QVariant>> data {
{ ModelList::NameRole, modelName },
{ ModelList::FilenameRole, modelFilename },
{ ModelList::FilesizeRole, "minimal" },
{ ModelList::OnlineRole, true },
{ ModelList::DescriptionRole,
tr("<strong>Mistral Medium model</strong><br>") + mistralDesc },
{ ModelList::RequiresVersionRole, "2.7.4" },
{ ModelList::OrderRole, "ce" },
{ ModelList::RamrequiredRole, 0 },
{ ModelList::ParametersRole, "?" },
{ ModelList::QuantRole, "NA" },
{ ModelList::TypeRole, "Mistral" },
{ ModelList::UrlRole, "https://api.mistral.ai/v1/chat/completions"},
};
updateData(id, data);
}
{
const QString nomicEmbedDesc = tr("<ul><li>For use with LocalDocs feature</li>"
"<li>Used for retrieval augmented generation (RAG)</li>"

Loading…
Cancel
Save