diff --git a/public/index.html b/public/index.html
index 28184acde..cdd687a62 100644
--- a/public/index.html
+++ b/public/index.html
@@ -382,6 +382,61 @@
$("#api_loading").css("display", 'none');
$("#api_button").css("display", 'inline-block');
}
+
+ async function getSoftPromptsList() {
+ if (!api_server) {
+ return;
+ }
+
+ const response = await fetch('/getsoftprompts', {
+ method: 'POST',
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ api_server: api_server }),
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ updateSoftPromptsList(data.soft_prompts);
+ }
+ }
+
+ function clearSoftPromptsList() {
+ $('#softprompt option[value!=""]').each(function() {
+ $(this).remove();
+ });
+ }
+
+ function updateSoftPromptsList(soft_prompts) {
+ // Delete SPs removed from Kobold
+ $('#softprompt option').each(function () {
+ const value = $(this).attr('value');
+
+ if (value == '') {
+ return;
+ }
+
+ const prompt = soft_prompts.find(x => x.name === value);
+ if (!prompt) {
+ $(this).remove();
+ }
+ });
+
+ // Add SPs added to Kobold
+ soft_prompts.forEach((prompt) => {
+ if ($(`#softprompt option[value="${prompt.name}"]`).length === 0) {
+ $('#softprompt').append(`${prompt.name} `);
+
+ if (prompt.selected) {
+ $('#softprompt').val(prompt.name);
+ }
+ }
+ });
+
+ // No SP selected or no SPs
+ if (soft_prompts.length === 0 || !(soft_prompts.some(x => x.selected))) {
+ $('#softprompt').val('');
+ }
+ }
function printCharaters(){
//console.log(1);
@@ -2034,6 +2089,8 @@
is_api_button_press = true;
getStatus();
detectUnitedKobold();
+ clearSoftPromptsList();
+ getSoftPromptsList();
}
});
@@ -2216,10 +2273,27 @@
is_get_status = false;
is_get_status_novel = false;
online_status = 'no_connection';
+ clearSoftPromptsList();
checkOnlineStatus();
changeMainAPI();
saveSettings();
});
+ $('#softprompt').change(async function() {
+ if (!api_server) {
+ return;
+ }
+
+ const selected = $('#softprompt').find(':selected').val();
+ const response = await fetch('/setsoftprompt', {
+ method: 'POST',
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ name: selected, api_server: api_server }),
+ });
+
+ if (!response.ok) {
+ console.error("Couldn't change soft prompt");
+ }
+ });
function changeMainAPI(){
if($('#main_api').find(":selected").val() == 'kobold'){
$('#kobold_api').css("display", "block");
@@ -2228,6 +2302,7 @@
$('#max_context_block').css('display', 'block');
$('#amount_gen_block').css('display', 'block');
$('#world_info_block').css('display', 'flex');
+ $('#softprompt_block').css('display', 'block');
}
if($('#main_api').find(":selected").val() == 'novel'){
$('#kobold_api').css("display", "none");
@@ -2236,6 +2311,7 @@
$('#max_context_block').css('display', 'none');
$('#amount_gen_block').css('display', 'none');
$('#world_info_block').css('display', 'none');
+ $('#softprompt_block').css('display', 'none');
}
updateWorldStatus();
@@ -3827,6 +3903,11 @@
+ Soft Prompt About soft prompts (? )
+
+
+ None
+
diff --git a/public/notes/14.html b/public/notes/14.html
new file mode 100644
index 000000000..457f096a6
--- /dev/null
+++ b/public/notes/14.html
@@ -0,0 +1,27 @@
+
+
+
Soft Prompts
+
+
+
+
+
+
+
+
Soft Prompts
+
Soft Prompts allow you to customize the style and behavior of your AI.
+
+ They are created by training the AI with a special type of prompt using a collection of input data.
+ Experimenting with different soft prompts can lead to exciting and unique results.
+ The most successful soft prompts are those that align the AI's output with a literary genre, fictional universe, or the style of a particular author.
+
+
+
Common Misconceptions
+
+ Soft prompts do not provide new information to the model, but can effectively influence the model's tone, word choice, and formatting.
+ Soft prompts are not a means of compressing a full prompt into a limited token space. Instead, they provide a way to guide the language model's output through data in the context.
+
+
+
+
+
diff --git a/public/style.css b/public/style.css
index 1db3216ae..46c8a568a 100644
--- a/public/style.css
+++ b/public/style.css
@@ -1415,6 +1415,14 @@ select {
background-color: rgb(36, 37, 37);
}
+#softprompt {
+ width: 284px;
+ margin-left: 10px;
+ margin-bottom: 35px;
+ color: #ffffff9d;
+ box-shadow: 0 0 2px rgba(200, 200, 200, 0.5);
+ background-color: #13152c;
+}
.option_select_right_menu{
width:284px;
diff --git a/server.js b/server.js
index 335220148..b6e37a339 100644
--- a/server.js
+++ b/server.js
@@ -362,6 +362,79 @@ app.post("/getstatus", jsonParser, function(request, response_getstatus = respon
response_getstatus.send({result: "no_connection"});
});
});
+
+const formatApiUrl = (url) => (url.indexOf('localhost') !== -1)
+ ? url.replace('localhost', '127.0.0.1')
+ : url;
+
+// TODO Rewrite using async wrapper from worldinfo branch
+app.post('/getsoftprompts', jsonParser, async function (request, response) {
+ if (!request.body || !request.body.api_server) {
+ return response.sendStatus(400);
+ }
+
+ const baseUrl = formatApiUrl(request.body.api_server);
+ let soft_prompts = [];
+
+ try {
+ var args = { headers: { "Content-Type": "application/json" } };
+ const softPromptsList = await new Promise((resolve, reject) => {
+ client.get(`${baseUrl}/v1/config/soft_prompts_list`, args, function (data, response) {
+ if (response.statusCode == 200) {
+ const nameList = data.values.map(x => x.value);
+ resolve(nameList);
+ }
+ else {
+ reject(response.status);
+ }
+ }).on('error', function (err) {
+ reject(err);
+ });
+ });
+
+ const softPromptSelected = await new Promise((resolve, reject) => {
+ client.get(`${baseUrl}/v1/config/soft_prompt`, args, function (data, response) {
+ if (response.statusCode == 200) {
+ resolve(data.value);
+ }
+ else {
+ reject(response.status);
+ }
+ }).on('error', function (err) {
+ reject(err);
+ });
+ });
+
+ soft_prompts = softPromptsList.map(x => ({ name: x, selected: x === softPromptSelected }));
+ } catch (err) {
+ soft_prompts = [];
+ }
+
+ return response.send({ soft_prompts });
+});
+
+// TODO Rewrite using async wrapper from worldinfo branch
+app.post("/setsoftprompt", jsonParser, async function(request, response) {
+ if (!request.body || !request.body.api_server) {
+ return response.sendStatus(400);
+ }
+
+ const baseUrl = formatApiUrl(request.body.api_server);
+ const args = {
+ headers: { "Content-Type": "application/json" },
+ data: { value: request.body.name ?? '' },
+ };
+ client.put(`${baseUrl}/v1/config/soft_prompt`, args, function (_, res) {
+ if (res.statusCode == 200) {
+ return response.sendStatus(200);
+ } else {
+ return response.sendStatus(500);
+ }
+ }).on('error', () => {
+ return response.sendStatus(500);
+ });
+});
+
function checkServer(){
//console.log('Check run###################################################');
api_server = 'http://127.0.0.1:5000';