mirror of
https://github.com/nomic-ai/gpt4all.git
synced 2025-08-15 06:33:31 +00:00
Refactor and make use of jinja templates.
Signed-off-by: Adam Treat <treat.adam@gmail.com>
This commit is contained in:
parent
00ecbb75b4
commit
c3cfaff803
@ -306,7 +306,7 @@ else()
|
|||||||
PRIVATE Qt6::Quick Qt6::Svg Qt6::HttpServer Qt6::Sql Qt6::Pdf)
|
PRIVATE Qt6::Quick Qt6::Svg Qt6::HttpServer Qt6::Sql Qt6::Pdf)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(chat
|
target_link_libraries(chat
|
||||||
PRIVATE llmodel)
|
PRIVATE llmodel jinja2cpp)
|
||||||
|
|
||||||
|
|
||||||
# -- install --
|
# -- install --
|
||||||
|
@ -42,6 +42,56 @@ QString BraveSearch::run(const QJsonObject ¶meters, qint64 timeout)
|
|||||||
return worker.response();
|
return worker.response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject BraveSearch::paramSchema() const
|
||||||
|
{
|
||||||
|
static const QString braveParamSchema = R"({
|
||||||
|
"apiKey": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The api key to use",
|
||||||
|
"required": true,
|
||||||
|
"modelGenerated": false,
|
||||||
|
"userConfigured": true
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The query to search",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The number of excerpts to return",
|
||||||
|
"required": true,
|
||||||
|
"modelGenerated": false
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
static const QJsonDocument braveJsonDoc = QJsonDocument::fromJson(braveParamSchema.toUtf8());
|
||||||
|
Q_ASSERT(!braveJsonDoc.isNull() && braveJsonDoc.isObject());
|
||||||
|
return braveJsonDoc.object();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject BraveSearch::exampleParams() const
|
||||||
|
{
|
||||||
|
static const QString example = R"({
|
||||||
|
"query": "the 44th president of the United States"
|
||||||
|
})";
|
||||||
|
static const QJsonDocument exampleDoc = QJsonDocument::fromJson(example.toUtf8());
|
||||||
|
Q_ASSERT(!exampleDoc.isNull() && exampleDoc.isObject());
|
||||||
|
return exampleDoc.object();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BraveSearch::isEnabled() const
|
||||||
|
{
|
||||||
|
// FIXME: Refer to mysettings
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BraveSearch::forceUsage() const
|
||||||
|
{
|
||||||
|
// FIXME: Refer to mysettings
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void BraveAPIWorker::request(const QString &apiKey, const QString &query, int count)
|
void BraveAPIWorker::request(const QString &apiKey, const QString &query, int count)
|
||||||
{
|
{
|
||||||
// Documentation on the brave web search:
|
// Documentation on the brave web search:
|
||||||
|
@ -48,6 +48,16 @@ public:
|
|||||||
ToolEnums::Error error() const override { return m_error; }
|
ToolEnums::Error error() const override { return m_error; }
|
||||||
QString errorString() const override { return m_errorString; }
|
QString errorString() const override { return m_errorString; }
|
||||||
|
|
||||||
|
QString name() const override { return tr("Brave web search"); }
|
||||||
|
QString description() const override { return tr("Search the web using brave"); }
|
||||||
|
QString function() const override { return "brave_search"; }
|
||||||
|
QJsonObject paramSchema() const override;
|
||||||
|
QJsonObject exampleParams() const override;
|
||||||
|
bool isEnabled() const override;
|
||||||
|
bool isBuiltin() const override { return true; }
|
||||||
|
bool forceUsage() const override;
|
||||||
|
bool excerpts() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ToolEnums::Error m_error;
|
ToolEnums::Error m_error;
|
||||||
QString m_errorString;
|
QString m_errorString;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "localdocssearch.h"
|
#include "localdocssearch.h"
|
||||||
#include "mysettings.h"
|
#include "mysettings.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
#include "tool.h"
|
||||||
|
#include "toolmodel.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@ -29,6 +31,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <jinja2cpp/template.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@ -1332,7 +1335,35 @@ void ChatLLM::processSystemPrompt()
|
|||||||
if (!isModelLoaded() || m_processedSystemPrompt || m_restoreStateFromText || m_isServer)
|
if (!isModelLoaded() || m_processedSystemPrompt || m_restoreStateFromText || m_isServer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::string systemPrompt = MySettings::globalInstance()->modelSystemPrompt(m_modelInfo).toStdString();
|
const std::string systemPromptTemplate = MySettings::globalInstance()->modelSystemPromptTemplate(m_modelInfo).toStdString();
|
||||||
|
|
||||||
|
// FIXME: This needs to be moved to settings probably and the same code used for validation
|
||||||
|
jinja2::ValuesMap params;
|
||||||
|
params.insert({"currentDate", QDate::currentDate().toString().toStdString()});
|
||||||
|
|
||||||
|
jinja2::ValuesList toolList;
|
||||||
|
int c = ToolModel::globalInstance()->count();
|
||||||
|
for (int i = 0; i < c; ++i) {
|
||||||
|
Tool *t = ToolModel::globalInstance()->get(i);
|
||||||
|
if (t->isEnabled() && !t->forceUsage())
|
||||||
|
toolList.push_back(t->jinjaValue());
|
||||||
|
}
|
||||||
|
params.insert({"toolList", toolList});
|
||||||
|
|
||||||
|
std::string systemPrompt;
|
||||||
|
|
||||||
|
jinja2::Template t;
|
||||||
|
t.Load(systemPromptTemplate);
|
||||||
|
const auto renderResult = t.RenderAsString(params);
|
||||||
|
|
||||||
|
// The GUI should not allow setting an improper template, but it is always possible someone hand
|
||||||
|
// edits the settings file to produce an improper one.
|
||||||
|
Q_ASSERT(renderResult);
|
||||||
|
if (renderResult)
|
||||||
|
systemPrompt = renderResult.value();
|
||||||
|
else
|
||||||
|
qWarning() << "ERROR: Could not parse system prompt template:" << renderResult.error().ToString();
|
||||||
|
|
||||||
if (QString::fromStdString(systemPrompt).trimmed().isEmpty()) {
|
if (QString::fromStdString(systemPrompt).trimmed().isEmpty()) {
|
||||||
m_processedSystemPrompt = true;
|
m_processedSystemPrompt = true;
|
||||||
return;
|
return;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
@ -39,6 +40,37 @@ QString LocalDocsSearch::run(const QJsonObject ¶meters, qint64 timeout)
|
|||||||
return worker.response();
|
return worker.response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject LocalDocsSearch::paramSchema() const
|
||||||
|
{
|
||||||
|
static const QString localParamSchema = R"({
|
||||||
|
"collections": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "The collections to search",
|
||||||
|
"required": true,
|
||||||
|
"modelGenerated": false,
|
||||||
|
"userConfigured": false
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The query to search",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The number of excerpts to return",
|
||||||
|
"required": true,
|
||||||
|
"modelGenerated": false
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
static const QJsonDocument localJsonDoc = QJsonDocument::fromJson(localParamSchema.toUtf8());
|
||||||
|
Q_ASSERT(!localJsonDoc.isNull() && localJsonDoc.isObject());
|
||||||
|
return localJsonDoc.object();
|
||||||
|
}
|
||||||
|
|
||||||
LocalDocsWorker::LocalDocsWorker()
|
LocalDocsWorker::LocalDocsWorker()
|
||||||
: QObject(nullptr)
|
: QObject(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,15 @@ public:
|
|||||||
ToolEnums::Error error() const override { return m_error; }
|
ToolEnums::Error error() const override { return m_error; }
|
||||||
QString errorString() const override { return m_errorString; }
|
QString errorString() const override { return m_errorString; }
|
||||||
|
|
||||||
|
QString name() const override { return tr("LocalDocs search"); }
|
||||||
|
QString description() const override { return tr("Search the local docs"); }
|
||||||
|
QString function() const override { return "localdocs_search"; }
|
||||||
|
QJsonObject paramSchema() const override;
|
||||||
|
bool isEnabled() const override { return true; }
|
||||||
|
bool isBuiltin() const override { return true; }
|
||||||
|
bool forceUsage() const override { return true; }
|
||||||
|
bool excerpts() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ToolEnums::Error m_error;
|
ToolEnums::Error m_error;
|
||||||
QString m_errorString;
|
QString m_errorString;
|
||||||
|
@ -334,15 +334,15 @@ void ModelInfo::setToolTemplate(const QString &t)
|
|||||||
m_toolTemplate = t;
|
m_toolTemplate = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ModelInfo::systemPrompt() const
|
QString ModelInfo::systemPromptTemplate() const
|
||||||
{
|
{
|
||||||
return MySettings::globalInstance()->modelSystemPrompt(*this);
|
return MySettings::globalInstance()->modelSystemPromptTemplate(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelInfo::setSystemPrompt(const QString &p)
|
void ModelInfo::setSystemPromptTemplate(const QString &p)
|
||||||
{
|
{
|
||||||
if (shouldSaveMetadata()) MySettings::globalInstance()->setModelSystemPrompt(*this, p, true /*force*/);
|
if (shouldSaveMetadata()) MySettings::globalInstance()->setModelSystemPromptTemplate(*this, p, true /*force*/);
|
||||||
m_systemPrompt = p;
|
m_systemPromptTemplate = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ModelInfo::chatNamePrompt() const
|
QString ModelInfo::chatNamePrompt() const
|
||||||
@ -397,7 +397,7 @@ QVariantMap ModelInfo::getFields() const
|
|||||||
{ "repeatPenaltyTokens", m_repeatPenaltyTokens },
|
{ "repeatPenaltyTokens", m_repeatPenaltyTokens },
|
||||||
{ "promptTemplate", m_promptTemplate },
|
{ "promptTemplate", m_promptTemplate },
|
||||||
{ "toolTemplate", m_toolTemplate },
|
{ "toolTemplate", m_toolTemplate },
|
||||||
{ "systemPrompt", m_systemPrompt },
|
{ "systemPromptTemplate",m_systemPromptTemplate },
|
||||||
{ "chatNamePrompt", m_chatNamePrompt },
|
{ "chatNamePrompt", m_chatNamePrompt },
|
||||||
{ "suggestedFollowUpPrompt", m_suggestedFollowUpPrompt },
|
{ "suggestedFollowUpPrompt", m_suggestedFollowUpPrompt },
|
||||||
};
|
};
|
||||||
@ -792,7 +792,7 @@ QVariant ModelList::dataInternal(const ModelInfo *info, int role) const
|
|||||||
case ToolTemplateRole:
|
case ToolTemplateRole:
|
||||||
return info->toolTemplate();
|
return info->toolTemplate();
|
||||||
case SystemPromptRole:
|
case SystemPromptRole:
|
||||||
return info->systemPrompt();
|
return info->systemPromptTemplate();
|
||||||
case ChatNamePromptRole:
|
case ChatNamePromptRole:
|
||||||
return info->chatNamePrompt();
|
return info->chatNamePrompt();
|
||||||
case SuggestedFollowUpPromptRole:
|
case SuggestedFollowUpPromptRole:
|
||||||
@ -970,7 +970,7 @@ void ModelList::updateData(const QString &id, const QVector<QPair<int, QVariant>
|
|||||||
case ToolTemplateRole:
|
case ToolTemplateRole:
|
||||||
info->setToolTemplate(value.toString()); break;
|
info->setToolTemplate(value.toString()); break;
|
||||||
case SystemPromptRole:
|
case SystemPromptRole:
|
||||||
info->setSystemPrompt(value.toString()); break;
|
info->setSystemPromptTemplate(value.toString()); break;
|
||||||
case ChatNamePromptRole:
|
case ChatNamePromptRole:
|
||||||
info->setChatNamePrompt(value.toString()); break;
|
info->setChatNamePrompt(value.toString()); break;
|
||||||
case SuggestedFollowUpPromptRole:
|
case SuggestedFollowUpPromptRole:
|
||||||
@ -1125,7 +1125,7 @@ QString ModelList::clone(const ModelInfo &model)
|
|||||||
{ ModelList::RepeatPenaltyTokensRole, model.repeatPenaltyTokens() },
|
{ ModelList::RepeatPenaltyTokensRole, model.repeatPenaltyTokens() },
|
||||||
{ ModelList::PromptTemplateRole, model.promptTemplate() },
|
{ ModelList::PromptTemplateRole, model.promptTemplate() },
|
||||||
{ ModelList::ToolTemplateRole, model.toolTemplate() },
|
{ ModelList::ToolTemplateRole, model.toolTemplate() },
|
||||||
{ ModelList::SystemPromptRole, model.systemPrompt() },
|
{ ModelList::SystemPromptRole, model.systemPromptTemplate() },
|
||||||
{ ModelList::ChatNamePromptRole, model.chatNamePrompt() },
|
{ ModelList::ChatNamePromptRole, model.chatNamePrompt() },
|
||||||
{ ModelList::SuggestedFollowUpPromptRole, model.suggestedFollowUpPrompt() },
|
{ ModelList::SuggestedFollowUpPromptRole, model.suggestedFollowUpPrompt() },
|
||||||
};
|
};
|
||||||
|
@ -69,7 +69,7 @@ struct ModelInfo {
|
|||||||
Q_PROPERTY(int repeatPenaltyTokens READ repeatPenaltyTokens WRITE setRepeatPenaltyTokens)
|
Q_PROPERTY(int repeatPenaltyTokens READ repeatPenaltyTokens WRITE setRepeatPenaltyTokens)
|
||||||
Q_PROPERTY(QString promptTemplate READ promptTemplate WRITE setPromptTemplate)
|
Q_PROPERTY(QString promptTemplate READ promptTemplate WRITE setPromptTemplate)
|
||||||
Q_PROPERTY(QString toolTemplate READ toolTemplate WRITE setToolTemplate)
|
Q_PROPERTY(QString toolTemplate READ toolTemplate WRITE setToolTemplate)
|
||||||
Q_PROPERTY(QString systemPrompt READ systemPrompt WRITE setSystemPrompt)
|
Q_PROPERTY(QString systemPromptTemplate READ systemPromptTemplate WRITE setSystemPromptTemplate)
|
||||||
Q_PROPERTY(QString chatNamePrompt READ chatNamePrompt WRITE setChatNamePrompt)
|
Q_PROPERTY(QString chatNamePrompt READ chatNamePrompt WRITE setChatNamePrompt)
|
||||||
Q_PROPERTY(QString suggestedFollowUpPrompt READ suggestedFollowUpPrompt WRITE setSuggestedFollowUpPrompt)
|
Q_PROPERTY(QString suggestedFollowUpPrompt READ suggestedFollowUpPrompt WRITE setSuggestedFollowUpPrompt)
|
||||||
Q_PROPERTY(int likes READ likes WRITE setLikes)
|
Q_PROPERTY(int likes READ likes WRITE setLikes)
|
||||||
@ -181,8 +181,9 @@ public:
|
|||||||
void setPromptTemplate(const QString &t);
|
void setPromptTemplate(const QString &t);
|
||||||
QString toolTemplate() const;
|
QString toolTemplate() const;
|
||||||
void setToolTemplate(const QString &t);
|
void setToolTemplate(const QString &t);
|
||||||
QString systemPrompt() const;
|
QString systemPromptTemplate() const;
|
||||||
void setSystemPrompt(const QString &p);
|
void setSystemPromptTemplate(const QString &p);
|
||||||
|
// FIXME (adam): The chatname and suggested follow-up should also be templates I guess?
|
||||||
QString chatNamePrompt() const;
|
QString chatNamePrompt() const;
|
||||||
void setChatNamePrompt(const QString &p);
|
void setChatNamePrompt(const QString &p);
|
||||||
QString suggestedFollowUpPrompt() const;
|
QString suggestedFollowUpPrompt() const;
|
||||||
@ -219,7 +220,7 @@ private:
|
|||||||
int m_repeatPenaltyTokens = 64;
|
int m_repeatPenaltyTokens = 64;
|
||||||
QString m_promptTemplate = "### Human:\n%1\n\n### Assistant:\n";
|
QString m_promptTemplate = "### Human:\n%1\n\n### Assistant:\n";
|
||||||
QString m_toolTemplate = "";
|
QString m_toolTemplate = "";
|
||||||
QString m_systemPrompt = "### System:\nYou are an AI assistant who gives a quality response to whatever humans ask of you.\n\n";
|
QString m_systemPromptTemplate = "### System:\nYou are an AI assistant who gives a quality response to whatever humans ask of you.\n\n";
|
||||||
QString m_chatNamePrompt = "Describe the above conversation in seven words or less.";
|
QString m_chatNamePrompt = "Describe the above conversation in seven words or less.";
|
||||||
QString m_suggestedFollowUpPrompt = "Suggest three very short factual follow-up questions that have not been answered yet or cannot be found inspired by the previous conversation and excerpts.";
|
QString m_suggestedFollowUpPrompt = "Suggest three very short factual follow-up questions that have not been answered yet or cannot be found inspired by the previous conversation and excerpts.";
|
||||||
friend class MySettings;
|
friend class MySettings;
|
||||||
|
@ -195,7 +195,7 @@ void MySettings::restoreModelDefaults(const ModelInfo &info)
|
|||||||
setModelRepeatPenaltyTokens(info, info.m_repeatPenaltyTokens);
|
setModelRepeatPenaltyTokens(info, info.m_repeatPenaltyTokens);
|
||||||
setModelPromptTemplate(info, info.m_promptTemplate);
|
setModelPromptTemplate(info, info.m_promptTemplate);
|
||||||
setModelToolTemplate(info, info.m_toolTemplate);
|
setModelToolTemplate(info, info.m_toolTemplate);
|
||||||
setModelSystemPrompt(info, info.m_systemPrompt);
|
setModelSystemPromptTemplate(info, info.m_systemPromptTemplate);
|
||||||
setModelChatNamePrompt(info, info.m_chatNamePrompt);
|
setModelChatNamePrompt(info, info.m_chatNamePrompt);
|
||||||
setModelSuggestedFollowUpPrompt(info, info.m_suggestedFollowUpPrompt);
|
setModelSuggestedFollowUpPrompt(info, info.m_suggestedFollowUpPrompt);
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ double MySettings::modelRepeatPenalty (const ModelInfo &info) const
|
|||||||
int MySettings::modelRepeatPenaltyTokens (const ModelInfo &info) const { return getModelSetting("repeatPenaltyTokens", info).toInt(); }
|
int MySettings::modelRepeatPenaltyTokens (const ModelInfo &info) const { return getModelSetting("repeatPenaltyTokens", info).toInt(); }
|
||||||
QString MySettings::modelPromptTemplate (const ModelInfo &info) const { return getModelSetting("promptTemplate", info).toString(); }
|
QString MySettings::modelPromptTemplate (const ModelInfo &info) const { return getModelSetting("promptTemplate", info).toString(); }
|
||||||
QString MySettings::modelToolTemplate (const ModelInfo &info) const { return getModelSetting("toolTemplate", info).toString(); }
|
QString MySettings::modelToolTemplate (const ModelInfo &info) const { return getModelSetting("toolTemplate", info).toString(); }
|
||||||
QString MySettings::modelSystemPrompt (const ModelInfo &info) const { return getModelSetting("systemPrompt", info).toString(); }
|
QString MySettings::modelSystemPromptTemplate (const ModelInfo &info) const { return getModelSetting("systemPrompt", info).toString(); }
|
||||||
QString MySettings::modelChatNamePrompt (const ModelInfo &info) const { return getModelSetting("chatNamePrompt", info).toString(); }
|
QString MySettings::modelChatNamePrompt (const ModelInfo &info) const { return getModelSetting("chatNamePrompt", info).toString(); }
|
||||||
QString MySettings::modelSuggestedFollowUpPrompt(const ModelInfo &info) const { return getModelSetting("suggestedFollowUpPrompt", info).toString(); }
|
QString MySettings::modelSuggestedFollowUpPrompt(const ModelInfo &info) const { return getModelSetting("suggestedFollowUpPrompt", info).toString(); }
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ void MySettings::setModelToolTemplate(const ModelInfo &info, const QString &valu
|
|||||||
setModelSetting("toolTemplate", info, value, force, true);
|
setModelSetting("toolTemplate", info, value, force, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySettings::setModelSystemPrompt(const ModelInfo &info, const QString &value, bool force)
|
void MySettings::setModelSystemPromptTemplate(const ModelInfo &info, const QString &value, bool force)
|
||||||
{
|
{
|
||||||
setModelSetting("systemPrompt", info, value, force, true);
|
setModelSetting("systemPrompt", info, value, force, true);
|
||||||
}
|
}
|
||||||
|
@ -128,8 +128,8 @@ public:
|
|||||||
Q_INVOKABLE void setModelPromptTemplate(const ModelInfo &info, const QString &value, bool force = false);
|
Q_INVOKABLE void setModelPromptTemplate(const ModelInfo &info, const QString &value, bool force = false);
|
||||||
QString modelToolTemplate(const ModelInfo &info) const;
|
QString modelToolTemplate(const ModelInfo &info) const;
|
||||||
Q_INVOKABLE void setModelToolTemplate(const ModelInfo &info, const QString &value, bool force = false);
|
Q_INVOKABLE void setModelToolTemplate(const ModelInfo &info, const QString &value, bool force = false);
|
||||||
QString modelSystemPrompt(const ModelInfo &info) const;
|
QString modelSystemPromptTemplate(const ModelInfo &info) const;
|
||||||
Q_INVOKABLE void setModelSystemPrompt(const ModelInfo &info, const QString &value, bool force = false);
|
Q_INVOKABLE void setModelSystemPromptTemplate(const ModelInfo &info, const QString &value, bool force = false);
|
||||||
int modelContextLength(const ModelInfo &info) const;
|
int modelContextLength(const ModelInfo &info) const;
|
||||||
Q_INVOKABLE void setModelContextLength(const ModelInfo &info, int value, bool force = false);
|
Q_INVOKABLE void setModelContextLength(const ModelInfo &info, int value, bool force = false);
|
||||||
int modelGpuLayers(const ModelInfo &info) const;
|
int modelGpuLayers(const ModelInfo &info) const;
|
||||||
|
@ -1 +1,31 @@
|
|||||||
#include "tool.h"
|
#include "tool.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
QJsonObject filterModelGeneratedProperties(const QJsonObject &inputObject) {
|
||||||
|
QJsonObject filteredObject;
|
||||||
|
for (const QString &key : inputObject.keys()) {
|
||||||
|
QJsonObject propertyObject = inputObject.value(key).toObject();
|
||||||
|
if (!propertyObject.contains("modelGenerated") || propertyObject["modelGenerated"].toBool())
|
||||||
|
filteredObject.insert(key, propertyObject);
|
||||||
|
}
|
||||||
|
return filteredObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
jinja2::Value Tool::jinjaValue() const
|
||||||
|
{
|
||||||
|
QJsonDocument doc(filterModelGeneratedProperties(paramSchema()));
|
||||||
|
QString p(doc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
QJsonDocument exampleDoc(exampleParams());
|
||||||
|
QString e(exampleDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
jinja2::ValuesMap params {
|
||||||
|
{ "name", name().toStdString() },
|
||||||
|
{ "description", description().toStdString() },
|
||||||
|
{ "function", function().toStdString() },
|
||||||
|
{ "paramSchema", p.toStdString() },
|
||||||
|
{ "exampleParams", e.toStdString() }
|
||||||
|
};
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <jinja2cpp/value.h>
|
||||||
|
|
||||||
using namespace Qt::Literals::StringLiterals;
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
|
||||||
@ -18,15 +19,16 @@ namespace ToolEnums {
|
|||||||
|
|
||||||
class Tool : public QObject {
|
class Tool : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString name MEMBER name)
|
Q_PROPERTY(QString name READ name CONSTANT)
|
||||||
Q_PROPERTY(QString description MEMBER description)
|
Q_PROPERTY(QString description READ description CONSTANT)
|
||||||
Q_PROPERTY(QString function MEMBER function)
|
Q_PROPERTY(QString function READ function CONSTANT)
|
||||||
Q_PROPERTY(QJsonObject paramSchema MEMBER paramSchema)
|
Q_PROPERTY(QJsonObject paramSchema READ paramSchema CONSTANT)
|
||||||
Q_PROPERTY(QUrl url MEMBER url)
|
Q_PROPERTY(QJsonObject exampleParams READ exampleParams CONSTANT)
|
||||||
Q_PROPERTY(bool isEnabled MEMBER isEnabled)
|
Q_PROPERTY(QUrl url READ url CONSTANT)
|
||||||
Q_PROPERTY(bool isBuiltin MEMBER isBuiltin)
|
Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY isEnabledChanged)
|
||||||
Q_PROPERTY(bool forceUsage MEMBER forceUsage)
|
Q_PROPERTY(bool isBuiltin READ isBuiltin CONSTANT)
|
||||||
Q_PROPERTY(bool excerpts MEMBER excerpts)
|
Q_PROPERTY(bool forceUsage READ forceUsage NOTIFY forceUsageChanged)
|
||||||
|
Q_PROPERTY(bool excerpts READ excerpts CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Tool() : QObject(nullptr) {}
|
Tool() : QObject(nullptr) {}
|
||||||
@ -36,28 +38,54 @@ public:
|
|||||||
virtual ToolEnums::Error error() const { return ToolEnums::Error::NoError; }
|
virtual ToolEnums::Error error() const { return ToolEnums::Error::NoError; }
|
||||||
virtual QString errorString() const { return QString(); }
|
virtual QString errorString() const { return QString(); }
|
||||||
|
|
||||||
QString name; // [Required] Human readable name of the tool.
|
// [Required] Human readable name of the tool.
|
||||||
QString description; // [Required] Human readable description of the tool.
|
virtual QString name() const = 0;
|
||||||
QString function; // [Required] Must be unique. Name of the function to invoke. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
|
|
||||||
QJsonObject paramSchema; // [Optional] Json schema describing the tool's parameters. An empty object specifies no parameters.
|
|
||||||
// https://json-schema.org/understanding-json-schema/
|
|
||||||
QUrl url; // [Optional] The local file or remote resource use to invoke the tool.
|
|
||||||
bool isEnabled = false; // [Optional] Whether the tool is currently enabled
|
|
||||||
bool isBuiltin = false; // [Optional] Whether the tool is built-in
|
|
||||||
bool forceUsage = false; // [Optional] Whether we should attempt to force usage of the tool rather than let the LLM decide. NOTE: Not always possible.
|
|
||||||
bool excerpts = false; // [Optional] Whether json result produces source excerpts.
|
|
||||||
|
|
||||||
// FIXME: Should we go with essentially the OpenAI/ollama consensus for these tool
|
// [Required] Human readable description of the tool.
|
||||||
// info files? If you install a tool in GPT4All should it need to meet the spec for these:
|
virtual QString description() const = 0;
|
||||||
|
|
||||||
|
// [Required] Must be unique. Name of the function to invoke. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
|
||||||
|
virtual QString function() const = 0;
|
||||||
|
|
||||||
|
// [Optional] Json schema describing the tool's parameters. An empty object specifies no parameters.
|
||||||
|
// https://json-schema.org/understanding-json-schema/
|
||||||
// https://platform.openai.com/docs/api-reference/runs/createRun#runs-createrun-tools
|
// https://platform.openai.com/docs/api-reference/runs/createRun#runs-createrun-tools
|
||||||
// https://github.com/ollama/ollama/blob/main/docs/api.md#chat-request-with-tools
|
// https://github.com/ollama/ollama/blob/main/docs/api.md#chat-request-with-tools
|
||||||
|
// FIXME: This should be validated against json schema
|
||||||
|
virtual QJsonObject paramSchema() const { return QJsonObject(); }
|
||||||
|
|
||||||
|
// [Optional] An example of the parameters for this tool call. NOTE: This should only include parameters
|
||||||
|
// that the model is responsible for generating.
|
||||||
|
virtual QJsonObject exampleParams() const { return QJsonObject(); }
|
||||||
|
|
||||||
|
// [Optional] The local file or remote resource use to invoke the tool.
|
||||||
|
virtual QUrl url() const { return QUrl(); }
|
||||||
|
|
||||||
|
// [Optional] Whether the tool is currently enabled
|
||||||
|
virtual bool isEnabled() const { return false; }
|
||||||
|
|
||||||
|
// [Optional] Whether the tool is built-in
|
||||||
|
virtual bool isBuiltin() const { return false; }
|
||||||
|
|
||||||
|
// [Optional] Whether we should attempt to force usage of the tool rather than let the LLM decide. NOTE: Not always possible.
|
||||||
|
virtual bool forceUsage() const { return false; }
|
||||||
|
|
||||||
|
// [Optional] Whether json result produces source excerpts.
|
||||||
|
virtual bool excerpts() const { return false; }
|
||||||
|
|
||||||
bool operator==(const Tool &other) const {
|
bool operator==(const Tool &other) const {
|
||||||
return function == other.function;
|
return function() == other.function();
|
||||||
}
|
}
|
||||||
bool operator!=(const Tool &other) const {
|
bool operator!=(const Tool &other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jinja2::Value jinjaValue() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void isEnabledChanged();
|
||||||
|
void forceUsageChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOOL_H
|
#endif // TOOL_H
|
||||||
|
@ -20,79 +20,12 @@ ToolModel::ToolModel()
|
|||||||
QCoreApplication::instance()->installEventFilter(this);
|
QCoreApplication::instance()->installEventFilter(this);
|
||||||
|
|
||||||
Tool* localDocsSearch = new LocalDocsSearch;
|
Tool* localDocsSearch = new LocalDocsSearch;
|
||||||
localDocsSearch->name = tr("LocalDocs search");
|
|
||||||
localDocsSearch->description = tr("Search the local docs");
|
|
||||||
localDocsSearch->function = "localdocs_search";
|
|
||||||
localDocsSearch->isBuiltin = true;
|
|
||||||
localDocsSearch->excerpts = true;
|
|
||||||
localDocsSearch->forceUsage = true; // FIXME: persistent setting
|
|
||||||
localDocsSearch->isEnabled = true; // FIXME: persistent setting
|
|
||||||
|
|
||||||
QString localParamSchema = R"({
|
|
||||||
"collections": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"description": "The collections to search",
|
|
||||||
"required": true,
|
|
||||||
"modelGenerated": false,
|
|
||||||
"userConfigured": false
|
|
||||||
},
|
|
||||||
"query": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The query to search",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"count": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "The number of excerpts to return",
|
|
||||||
"required": true,
|
|
||||||
"modelGenerated": false
|
|
||||||
}
|
|
||||||
})";
|
|
||||||
|
|
||||||
QJsonDocument localJsonDoc = QJsonDocument::fromJson(localParamSchema.toUtf8());
|
|
||||||
Q_ASSERT(!localJsonDoc.isNull() && localJsonDoc.isObject());
|
|
||||||
localDocsSearch->paramSchema = localJsonDoc.object();
|
|
||||||
m_tools.append(localDocsSearch);
|
m_tools.append(localDocsSearch);
|
||||||
m_toolMap.insert(localDocsSearch->function, localDocsSearch);
|
m_toolMap.insert(localDocsSearch->function(), localDocsSearch);
|
||||||
|
|
||||||
Tool *braveSearch = new BraveSearch;
|
Tool *braveSearch = new BraveSearch;
|
||||||
braveSearch->name = tr("Brave web search");
|
|
||||||
braveSearch->description = tr("Search the web using brave.com");
|
|
||||||
braveSearch->function = "brave_search";
|
|
||||||
braveSearch->isBuiltin = true;
|
|
||||||
braveSearch->excerpts = true;
|
|
||||||
braveSearch->forceUsage = false; // FIXME: persistent setting
|
|
||||||
braveSearch->isEnabled = false; // FIXME: persistent setting
|
|
||||||
|
|
||||||
QString braveParamSchema = R"({
|
|
||||||
"apiKey": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The api key to use",
|
|
||||||
"required": true,
|
|
||||||
"modelGenerated": false,
|
|
||||||
"userConfigured": true
|
|
||||||
},
|
|
||||||
"query": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The query to search",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"count": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "The number of excerpts to return",
|
|
||||||
"required": true,
|
|
||||||
"modelGenerated": false
|
|
||||||
}
|
|
||||||
})";
|
|
||||||
|
|
||||||
QJsonDocument braveJsonDoc = QJsonDocument::fromJson(braveParamSchema.toUtf8());
|
|
||||||
Q_ASSERT(!braveJsonDoc.isNull() && braveJsonDoc.isObject());
|
|
||||||
braveSearch->paramSchema = braveJsonDoc.object();
|
|
||||||
m_tools.append(braveSearch);
|
m_tools.append(braveSearch);
|
||||||
m_toolMap.insert(braveSearch->function, braveSearch);
|
m_toolMap.insert(braveSearch->function(), braveSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToolModel::eventFilter(QObject *obj, QEvent *ev)
|
bool ToolModel::eventFilter(QObject *obj, QEvent *ev)
|
||||||
|
@ -41,23 +41,23 @@ public:
|
|||||||
const Tool *item = m_tools.at(index.row());
|
const Tool *item = m_tools.at(index.row());
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case NameRole:
|
case NameRole:
|
||||||
return item->name;
|
return item->name();
|
||||||
case DescriptionRole:
|
case DescriptionRole:
|
||||||
return item->description;
|
return item->description();
|
||||||
case FunctionRole:
|
case FunctionRole:
|
||||||
return item->function;
|
return item->function();
|
||||||
case ParametersRole:
|
case ParametersRole:
|
||||||
return item->paramSchema;
|
return item->paramSchema();
|
||||||
case UrlRole:
|
case UrlRole:
|
||||||
return item->url;
|
return item->url();
|
||||||
case IsEnabledRole:
|
case IsEnabledRole:
|
||||||
return item->isEnabled;
|
return item->isEnabled();
|
||||||
case IsBuiltinRole:
|
case IsBuiltinRole:
|
||||||
return item->isBuiltin;
|
return item->isBuiltin();
|
||||||
case ForceUsageRole:
|
case ForceUsageRole:
|
||||||
return item->forceUsage;
|
return item->forceUsage();
|
||||||
case ExcerptsRole:
|
case ExcerptsRole:
|
||||||
return item->excerpts;
|
return item->excerpts();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
Loading…
Reference in New Issue
Block a user