mirror of
https://github.com/LostRuins/koboldcpp.git
synced 2026-09-20 01:31:42 +02:00
Merge branch 'upstream' into concedo_experimental
# Conflicts: # .github/workflows/build-and-test-snapdragon.yml # .github/workflows/build-android.yml # .github/workflows/build-cache.yml # .github/workflows/build-cann.yml # .github/workflows/build-cross.yml # .github/workflows/build-openvino.yml # .github/workflows/build-riscv.yml # .github/workflows/build-sanitize.yml # .github/workflows/build-self-hosted.yml # .github/workflows/build-sycl.yml # .github/workflows/build-vulkan.yml # .github/workflows/build.yml # .github/workflows/release.yml # .github/workflows/server-sanitize.yml # ci/run.sh # docs/backend/SYCL.md # docs/backend/snapdragon/README.md # ggml/CMakeLists.txt # ggml/src/ggml-cuda/ggml-cuda.cu # ggml/src/ggml-hexagon/ggml-hexagon.cpp # ggml/src/ggml-hexagon/htp/CMakeLists.txt # ggml/src/ggml-hexagon/htp/cpy-ops.c # ggml/src/ggml-hexagon/htp/get-rows-ops.c # ggml/src/ggml-hexagon/htp/hmx-flash-attn-ops.c # ggml/src/ggml-hexagon/htp/htp-ctx.h # ggml/src/ggml-hexagon/htp/htp-ops.h # ggml/src/ggml-hexagon/htp/hvx-utils.h # ggml/src/ggml-hexagon/htp/main.c # ggml/src/ggml-hexagon/htp/rope-ops.c # ggml/src/ggml-hexagon/htp/set-rows-ops.c # ggml/src/ggml-hexagon/htp/unary-ops.c # ggml/src/ggml-sycl/common.hpp # ggml/src/ggml-sycl/ggml-sycl.cpp # ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp # ggml/src/ggml-webgpu/ggml-webgpu.cpp # ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl # ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl # ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl # scripts/sync-ggml.last # tests/gguf-model-data.cpp # tests/test-backend-ops.cpp
This commit is contained in:
+200
-37
@@ -6022,7 +6022,7 @@ Current version indicated by LITEVER below.
|
||||
inputtxt = replaceAll(inputtxt,instructsysplaceholder_end.trim(),get_instruct_systag_end(false));
|
||||
return inputtxt;
|
||||
}
|
||||
function replace_noninstruct_placeholders(inputtxt,escape=false,isgametext=true,persistent_countmap=null)
|
||||
function replace_chat_name_placeholders(inputtxt, escape=false)
|
||||
{
|
||||
let firstopponent = localsettings.chatopponent;
|
||||
if (firstopponent && firstopponent.includes("||$||")) {
|
||||
@@ -6040,7 +6040,11 @@ Current version indicated by LITEVER below.
|
||||
inputtxt = replaceAll(inputtxt,"{{user}}",(localsettings.chatname?localsettings.chatname:"User"),true);
|
||||
inputtxt = replaceAll(inputtxt,"{{char}}",(localsettings.chatopponent?firstopponent:defaultchatopponent),true);
|
||||
}
|
||||
|
||||
return inputtxt;
|
||||
}
|
||||
function replace_noninstruct_placeholders(inputtxt,escape=false,isgametext=true,persistent_countmap=null)
|
||||
{
|
||||
inputtxt = replace_chat_name_placeholders(inputtxt,escape);
|
||||
inputtxt = replaceAll(inputtxt,"{{original}}","",true); //redundant in Lite; use sysprompt or assistant jailbreak instead
|
||||
|
||||
for(let i=0;i<localsettings.placeholder_tags_data.length;++i)
|
||||
@@ -11771,6 +11775,7 @@ Current version indicated by LITEVER below.
|
||||
* @type {{
|
||||
* name: string;
|
||||
* urlParam: string;
|
||||
* matchers: string[];
|
||||
* inputBox: {
|
||||
* text: string;
|
||||
* placeholder: string;
|
||||
@@ -11784,6 +11789,7 @@ Current version indicated by LITEVER below.
|
||||
{
|
||||
name: "prompts.forthisfeel.club",
|
||||
urlParam: "aether",
|
||||
matchers: ["forthisfeel.club/"],
|
||||
inputBox: {
|
||||
text: "Enter prompts.forthisfeel.club prompt URL, or 4-digit prompt number",
|
||||
placeholder: "https://prompts.forthisfeel.club/1234"
|
||||
@@ -11852,6 +11858,7 @@ Current version indicated by LITEVER below.
|
||||
{
|
||||
name: "chub.ai / characterhub.org",
|
||||
urlParam: "chub",
|
||||
matchers: ["chub.ai/","characterhub.org/"],
|
||||
inputBox: {
|
||||
text: "Enter chub.ai or characterhub.org card URL",
|
||||
placeholder: "https://chub.ai/characters/Anonymous/example-character"
|
||||
@@ -11936,6 +11943,7 @@ Current version indicated by LITEVER below.
|
||||
{
|
||||
name: "pygmalion.chat",
|
||||
urlParam: "pyg",
|
||||
matchers: ["pygmalion.chat/"],
|
||||
inputBox: {
|
||||
text: "Enter pygmalion.chat character UUID",
|
||||
placeholder: "d7950ca8-c241-4725-8de1-42866e389ebf",
|
||||
@@ -12008,6 +12016,7 @@ Current version indicated by LITEVER below.
|
||||
{
|
||||
name: "aicharactercards.com",
|
||||
urlParam: "aicc",
|
||||
matchers: ["aicharactercards.com/"],
|
||||
inputBox: {
|
||||
text: "Enter aicharactercards.com card URL",
|
||||
placeholder: "https://aicharactercards.com/character-cards/work-jobs/deffcolony/lara-lightland",
|
||||
@@ -12096,6 +12105,7 @@ Current version indicated by LITEVER below.
|
||||
{
|
||||
name: "character-tavern.com",
|
||||
urlParam: "aicc",
|
||||
matchers: ["character-tavern.com/"],
|
||||
inputBox: {
|
||||
text: "Enter character-tavern.com card URL",
|
||||
placeholder: "https://character-tavern.com/character/yousef/Shinku",
|
||||
@@ -12180,6 +12190,138 @@ Current version indicated by LITEVER below.
|
||||
});
|
||||
}
|
||||
},
|
||||
//botbooru
|
||||
{
|
||||
name: "botbooru.com",
|
||||
urlParam: "botbooru",
|
||||
matchers: ["botbooru.com/"],
|
||||
inputBox: {
|
||||
text: "Enter botbooru.com card URL",
|
||||
placeholder: "https://botbooru.com/download/png/32104",
|
||||
},
|
||||
extraction: (userInput) => {
|
||||
if (userInput.match(/character\//i))
|
||||
{
|
||||
userInput = userInput.split("#")[0].split("?")[0];
|
||||
userInput = userInput.endsWith('/') ? userInput.slice(0, -1) : userInput;
|
||||
let tmp = userInput.split("character/")[1];
|
||||
return `https://botbooru.com/download/png/${tmp}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
userInput = userInput.split("#")[0].split("?")[0];
|
||||
userInput = userInput.endsWith('/') ? userInput.slice(0, -1) : userInput;
|
||||
return userInput;
|
||||
}
|
||||
},
|
||||
fetch: (userInput) => {
|
||||
temp_scenario = {
|
||||
"title":"",
|
||||
"desc": "",
|
||||
"opmode":3,
|
||||
"chatopponent": "",
|
||||
"gui_type":1,
|
||||
"prompt":"",
|
||||
"memory": "",
|
||||
"authorsnote": "",
|
||||
"worldinfo": [],
|
||||
};
|
||||
|
||||
finalurl = apply_proxy_url(userInput,true);
|
||||
//try to obtain the full portrait image
|
||||
return fetch(finalurl, {
|
||||
method: 'GET',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
})
|
||||
.then(rb => {
|
||||
if(rb.ok)
|
||||
{
|
||||
return rb.blob();
|
||||
}else{
|
||||
throw new Error('Cannot fetch tavern image');
|
||||
}
|
||||
})
|
||||
.then(blob => {
|
||||
preview_temp_scenario();
|
||||
|
||||
readTavernPngFromBlob(blob,(obj)=>{
|
||||
load_temp_scenario_from_tavernobj(obj);
|
||||
});
|
||||
|
||||
const objectURL = URL.createObjectURL(blob);
|
||||
const compressedImg = compressImage(objectURL, (compressedImageURI, aspectratio)=>{
|
||||
temp_scenario.image = compressedImageURI;
|
||||
temp_scenario.image_aspect = aspectratio;
|
||||
preview_temp_scenario();
|
||||
}, true, AVATAR_PX);
|
||||
})
|
||||
.catch(error => {
|
||||
throw new Error("Selected scenario is invalid.");
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
},
|
||||
//raw png URL download
|
||||
{
|
||||
name: "Raw URL",
|
||||
urlParam: "rawurl",
|
||||
matchers: ["/"],
|
||||
inputBox: {
|
||||
text: "Enter the direct URL to the character card file",
|
||||
placeholder: "https://example.com/file.png",
|
||||
},
|
||||
extraction: (userInput) => {
|
||||
return userInput;
|
||||
},
|
||||
fetch: (userInput) => {
|
||||
temp_scenario = {
|
||||
"title":"",
|
||||
"desc": "",
|
||||
"opmode":3,
|
||||
"chatopponent": "",
|
||||
"gui_type":1,
|
||||
"prompt":"",
|
||||
"memory": "",
|
||||
"authorsnote": "",
|
||||
"worldinfo": [],
|
||||
};
|
||||
|
||||
finalurl = apply_proxy_url(userInput,false);
|
||||
//try to obtain the full portrait image
|
||||
return fetch(finalurl, {
|
||||
method: 'GET',
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
})
|
||||
.then(rb => {
|
||||
if(rb.ok)
|
||||
{
|
||||
return rb.blob();
|
||||
}else{
|
||||
throw new Error('Cannot fetch tavern image');
|
||||
}
|
||||
})
|
||||
.then(blob => {
|
||||
preview_temp_scenario();
|
||||
|
||||
readTavernPngFromBlob(blob,(obj)=>{
|
||||
load_temp_scenario_from_tavernobj(obj);
|
||||
});
|
||||
|
||||
const objectURL = URL.createObjectURL(blob);
|
||||
const compressedImg = compressImage(objectURL, (compressedImageURI, aspectratio)=>{
|
||||
temp_scenario.image = compressedImageURI;
|
||||
temp_scenario.image_aspect = aspectratio;
|
||||
preview_temp_scenario();
|
||||
}, true, AVATAR_PX);
|
||||
})
|
||||
.catch(error => {
|
||||
throw new Error("Selected scenario is invalid.");
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// char-archive has shut down
|
||||
// {
|
||||
@@ -12308,7 +12450,7 @@ Current version indicated by LITEVER below.
|
||||
else inputBox(
|
||||
scenario_source.inputBox.text,
|
||||
"Import from " + scenario_source.name,
|
||||
"",
|
||||
getInputBoxValue(),
|
||||
scenario_source.inputBox.placeholder,
|
||||
(value) => {
|
||||
const input = getInputBoxValue().trim();
|
||||
@@ -12317,6 +12459,57 @@ Current version indicated by LITEVER below.
|
||||
);
|
||||
}
|
||||
|
||||
function import_scenario_unified_dropdown()
|
||||
{
|
||||
let dropdown = document.getElementById("importscenariounifieddropdown");
|
||||
if(dropdown)
|
||||
{
|
||||
let picked = dropdown.value;
|
||||
if(picked!="-1")
|
||||
{
|
||||
import_scenario(scenario_sources[picked]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function import_scenario_unified() //a single button entry point to import from any source
|
||||
{
|
||||
let combined_txt = "Please enter the full URL of the character card to import, or pick a specific website.";
|
||||
let selbox = `Source: <select style="padding:4px; display: inline; width: 200px; padding: 6px 3px;" class="form-control" id="importscenariounifieddropdown" onchange="import_scenario_unified_dropdown()">`;
|
||||
selbox += `<option value="-1">Automatic</option>`;
|
||||
for(let i=0;i<scenario_sources.length;++i)
|
||||
{
|
||||
selbox += `<option value="${i}">${scenario_sources[i].name}</option>`;
|
||||
}
|
||||
selbox += "</select>";
|
||||
combined_txt += "<br>" + selbox;
|
||||
|
||||
inputBox(combined_txt,"Import character card from URL","","Enter full URL to character card",
|
||||
(value) => {
|
||||
const input = getInputBoxValue().trim();
|
||||
let found = -1;
|
||||
for(let i=0;i<scenario_sources.length;++i)
|
||||
{
|
||||
for(let j=0;j<scenario_sources[i].matchers.length;++j)
|
||||
{
|
||||
let curr = scenario_sources[i].matchers[j].toLowerCase();
|
||||
if(curr && input.toLowerCase().includes(curr))
|
||||
{
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found!=-1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found!=-1)
|
||||
{
|
||||
import_scenario(scenario_sources[found],input);
|
||||
}
|
||||
},true);
|
||||
}
|
||||
|
||||
function display_scenarios()
|
||||
{
|
||||
mainmenu_untab(true);
|
||||
@@ -12327,10 +12520,7 @@ Current version indicated by LITEVER below.
|
||||
scenarios += `<button type="button" name="" class="scenarioitem purple btn btn-primary" onclick="hide_popups();document.getElementById('loadfileinput').click()">Load Character Card or JSON File</button>`;
|
||||
scenarios += `<button type="button" name="" class="scenarioitem purple btn btn-primary" onclick="hide_popups();display_scenariolibrary();">Load or Save Custom Scenario</button>`;
|
||||
scenarios += `<button type="button" name="" class="scenarioitem purple btn btn-primary" onclick="character_creator()">New Character Creator</button>`;
|
||||
|
||||
for(let i=0;i<scenario_sources.length;++i) {
|
||||
scenarios += `<button type="button" name="" class="scenarioitem purple btn btn-primary" onclick="import_scenario(scenario_sources[${i}])">${scenario_sources[i].name}</button>`
|
||||
}
|
||||
scenarios += `<button type="button" name="" class="scenarioitem purple btn btn-primary" onclick="import_scenario_unified()">Import from Website URL</button>`
|
||||
|
||||
for(let i=0;i<scenario_db.length;++i)
|
||||
{
|
||||
@@ -21849,35 +22039,6 @@ Current version indicated by LITEVER below.
|
||||
|
||||
}
|
||||
|
||||
//to reduce the prompt being flagged for CP on horde and failing, we sanitize it while trying to have as little impact on normal usage.
|
||||
//this does not affect the story context, only images sent
|
||||
//we only match whole words, to avoid the scunthorpe problem
|
||||
function sanitize_horde_image_prompt(inputtext) {
|
||||
if (inputtext == null || inputtext == "") { return ""; }
|
||||
|
||||
//to avoid flagging from some image models, always swap these words
|
||||
inputtext = inputtext.replace(/\b(girl)\b/gmi, "woman");
|
||||
inputtext = inputtext.replace(/\b(boy)\b/gmi, "man");
|
||||
inputtext = inputtext.replace(/\b(girls)\b/gmi, "women");
|
||||
inputtext = inputtext.replace(/\b(boys)\b/gmi, "men");
|
||||
|
||||
//always remove these high risk words from prompt, as they add little value to image gen while increasing the risk the prompt gets flagged
|
||||
inputtext = inputtext.replace(/\b(under.age|under.aged|underage|underaged|loli|pedo|pedophile|(\w+).year.old|(\w+).years.old|minor|prepubescent|minors|shota)\b/gmi, "");
|
||||
|
||||
//if nsfw is detected, do not remove it but apply additional precautions
|
||||
let foundnsfw = inputtext.match(/\b(cock|ahegao|hentai|uncensored|lewd|cocks|deepthroat|deepthroating|dick|dicks|cumshot|lesbian|fuck|fucked|fucking|sperm|naked|nipples|tits|boobs|breasts|boob|breast|topless|ass|butt|fingering|masturbate|masturbating|bitch|blowjob|pussy|piss|asshole|dildo|dildos|vibrator|erection|foreskin|handjob|nude|penis|porn|vibrator|virgin|vagina|vulva|threesome|orgy|bdsm|hickey|condom|testicles|anal|bareback|bukkake|creampie|stripper|strap-on|missionary|clitoris|clit|clitty|cowgirl|fleshlight|sex|buttplug|milf|oral|sucking|bondage|orgasm|scissoring|railed|slut|sluts|slutty|cumming|cunt|faggot|sissy|anal|anus|cum|semen|scat|nsfw|xxx|explicit|erotic|horny|aroused|jizz|moan|rape|raped|raping|throbbing|humping)\b/gmi);
|
||||
|
||||
if (foundnsfw) {
|
||||
//replace risky subject nouns with person
|
||||
inputtext = inputtext.replace(/\b(youngster|infant|baby|toddler|child|teen|kid|kiddie|kiddo|teenager|student|preteen|pre.teen)\b/gmi, "person");
|
||||
|
||||
//remove risky adjectives and related words
|
||||
inputtext = inputtext.replace(/\b(young|younger|youthful|youth|small|smaller|smallest|girly|boyish|lil|tiny|teenaged|lit[tl]le|school.aged|school|highschool|kindergarten|teens|children|kids)\b/gmi, "");
|
||||
}
|
||||
|
||||
return inputtext;
|
||||
}
|
||||
|
||||
function generate_new_image(sentence, base64img="", autoappend=true) //base64img is for img2img, autoappend automatically adds it to gametext arr
|
||||
{
|
||||
if(base64img!="")
|
||||
@@ -21904,7 +22065,6 @@ Current version indicated by LITEVER below.
|
||||
}
|
||||
|
||||
if (localsettings.generate_images_mode==1) { //horde
|
||||
sentence = sanitize_horde_image_prompt(sentence);
|
||||
usedscheduler = null; //horde does not use schedulers
|
||||
switch(usedsampler) //these names are used for horde only
|
||||
{
|
||||
@@ -26534,6 +26694,9 @@ Current version indicated by LITEVER below.
|
||||
let chatunits = []; //parse chat body into nice chat chunks
|
||||
let myturnchat = false; //who is currently speaking?
|
||||
|
||||
//fix: because chat operates on actual names, we MUST replace chat name placeholders early on.
|
||||
input = replace_chat_name_placeholders(input,false);
|
||||
|
||||
var othernamesregex = new RegExp("(?!" + localsettings.chatname + ").+?\: ", "gi");
|
||||
|
||||
if(!localsettings.chat_match_any_name && localsettings.chatopponent!="")
|
||||
|
||||
Reference in New Issue
Block a user