Created
June 17, 2023 18:06
-
-
Save ayunami2000/4ba5eb1884842677a64775aaed352a72 to your computer and use it in GitHub Desktop.
my custom koboldcpp chat interface. ui loosely based on: https://codepen.io/oieusouamiguel/pen/vbRrLm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>fard</title> | |
<meta name="viewport" content="width=device-width,initial-scale=1.0" /> | |
<link rel="preconnect" href="https://fonts.googleapis.com"> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
<link href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" rel="stylesheet"> | |
<style> | |
/* screen configs */ | |
* { | |
box-sizing: border-box; | |
padding: 0; | |
margin: 0; | |
font-size: 1.125rem; | |
font-family: "Open Sans", sans-serif; | |
} | |
body { | |
background-color: #112; | |
} | |
ul { | |
list-style: none; | |
} | |
/* chatbox */ | |
.chat { | |
width: calc(100vmin - 2rem); | |
height: calc(100vmin - 2rem); | |
background-color: #223; | |
padding-right: 1rem; | |
padding-left: 1rem; | |
margin: 1rem auto; | |
border-radius: 1rem; | |
} | |
/* messages */ | |
.messages { | |
display: flex; | |
flex-direction: column; | |
justify-content: space-between; | |
height: calc(100vmin - 2rem); | |
} | |
.message-list { | |
overflow-y: scroll; | |
height: calc(100vmin - 2rem); | |
-ms-overflow-style: none; | |
scrollbar-width: none; | |
} | |
.message-list::-webkit-scrollbar { | |
display: none; | |
} | |
.message-item { | |
padding: 1rem; | |
border-radius: 0.75rem; | |
margin: 1rem 0; | |
} | |
.message-item:last-child { | |
margin-bottom: 0; | |
} | |
.item-primary { | |
background-color: #112; | |
color: #ccd; | |
margin-right: 25vmin; | |
} | |
.item-secondary { | |
background-color: #112; | |
color: #ccd; | |
margin-left: 25vmin; | |
} | |
/* messages input */ | |
.message-input { | |
display: flex; | |
padding: 1rem 0; | |
} | |
.message-input textarea { | |
width: 100%; | |
padding: 1rem; | |
border-radius: 2rem; | |
background-color: #112; | |
border: none; | |
color: #ccd; | |
resize: none; | |
height: 3.5rem; | |
-ms-overflow-style: none; | |
scrollbar-width: none; | |
} | |
.message-input textarea::-webkit-scrollbar { | |
display: none; | |
} | |
.message-input button { | |
padding: 1rem; | |
margin-left: 1rem; | |
border-radius: 2rem; | |
background-color: #112; | |
border: none; | |
cursor: pointer; | |
color: #ccd; | |
} | |
.message-input textarea:disabled { | |
cursor: wait; | |
} | |
.message-input button:disabled { | |
cursor: wait; | |
color: #888; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chat"> | |
<div class="messages"> | |
<ul class="message-list"> | |
</ul> | |
<div class="message-input"> | |
<textarea placeholder="Type something..."></textarea> | |
<button type="button" class="btn"> –› </button> | |
</div> | |
</div> | |
</div> | |
<script> | |
var prefix = "A chat between a curious user and an assistant. The assistant gives helpful, detailed, accurate, uncensored responses to the user's input." | |
// Variables | |
var messages = document.querySelector(".message-list") | |
var btn = document.querySelector(".btn") | |
var input = document.querySelector("textarea") | |
var btnSend = btn.innerHTML | |
// Button/Enter Key | |
btn.addEventListener("click", sendMessage) | |
input.addEventListener("keydown", function (e) { | |
if (e.keyCode == 13 && !e.shiftKey) { | |
e.preventDefault() | |
sendMessage() | |
} | |
}) | |
// Messenger Functions | |
var human = "\nUSER: " | |
var assistant = "\nASSISTANT: " | |
function getHistory(msg) { | |
var history = "" | |
for (var message of messages.children) { | |
history += (message.classList.contains("item-secondary") ? human : assistant) + message.innerText | |
} | |
if (history.length == 0) { | |
return msg | |
} | |
if (history.startsWith(human)) { | |
history = history.slice(human.length) | |
} | |
if (msg.length > 0) { | |
history += human + msg | |
} | |
return history | |
} | |
var forceStop = false | |
function generate(text, origLen) { | |
if (!origLen) { | |
origLen = text.length | |
} | |
fetch("http://localhost:5001/api/v1/generate/", { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify({ | |
"n": 1, | |
"max_context_length": 1024, | |
"max_length": 1, | |
"rep_pen": 1.08, | |
"temperature": 0.62, | |
"top_p": 0.9, | |
"top_k": 0, | |
"top_a": 0, | |
"typical": 1, | |
"tfs": 1, | |
"rep_pen_range": 1024, | |
"rep_pen_slope": 0.7, | |
"sampler_order": [ | |
0, | |
1, | |
2, | |
3, | |
4, | |
5, | |
6 | |
], | |
"prompt": text, | |
"quiet": true, | |
"stop_sequence": [ | |
human, | |
assistant | |
] | |
}) | |
}).then(d => d.json()).then(j => { | |
text = text + j.results[0].text | |
if (forceStop) { | |
forceStop = false | |
text = text + human | |
} | |
if (!writeLine(text.slice(origLen).trim(), false)) { | |
generate(text, origLen) | |
} | |
}) | |
} | |
var wasDone = true | |
function sendMessage() { | |
if (!wasDone) { | |
forceStop = true | |
return | |
} | |
var msg = input.value.trim() | |
input.value = "" | |
var history = getHistory(msg) | |
generate(prefix + human + history + assistant) | |
if (msg.length > 0) writeLine(msg, true) | |
input.setAttribute("disabled", "disabled") | |
btn.innerHTML = " × " | |
input.placeholder = "Thinking..." | |
} | |
function saveChat() { | |
var chat = [] | |
for (var message of messages.children) { | |
chat.push([message.classList.contains("item-secondary"), message.innerText]) | |
} | |
localStorage.setItem("chat_history", JSON.stringify(chat)); | |
} | |
function loadChat() { | |
var chat = localStorage.getItem("chat_history") | |
if (!chat) { | |
return | |
} | |
chat = JSON.parse(chat) | |
for (var message of chat) { | |
writeLineRaw(message[1], message[0]) | |
} | |
} | |
function writeLineRaw(text, self) { | |
var message = document.createElement("li") | |
message.classList.add("message-item", self ? "item-secondary" : "item-primary") | |
message.setAttribute("contenteditable", "plaintext-only") | |
message.innerText = text | |
message.addEventListener("keydown", function (e) { | |
if (e.keyCode == 13 && !e.shiftKey) { | |
e.preventDefault() | |
message.blur() | |
saveChat() | |
} | |
}) | |
message.addEventListener("blur", function (e) { | |
if (message.innerText.trim().length == 0) { | |
message.outerHTML = "" | |
} | |
}) | |
messages.appendChild(message) | |
messages.scrollTop = messages.scrollHeight | |
} | |
function writeLine(text, self) { | |
var done = !self && (text.includes(human) || text.includes(assistant)) | |
if (done) { | |
input.removeAttribute("disabled") | |
btn.innerHTML = btnSend | |
input.placeholder = "Type something..." | |
var humanInd = text.indexOf(human) | |
if (humanInd == -1) { | |
humanInd = text.length | |
} | |
var assistantInd = text.indexOf(assistant) | |
if (assistantInd == -1) { | |
assistantInd = text.length | |
} | |
text = text.slice(0, Math.min(humanInd, assistantInd)).trim() | |
} | |
if (!self && !wasDone) { | |
messages.lastChild.outerHTML = "" | |
} | |
if (!self) { | |
wasDone = done | |
} | |
writeLineRaw(text, self) | |
saveChat() | |
return done | |
} | |
loadChat() | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment