llamacpphtmld/webui.go

214 lines
4.8 KiB
Go

package main
import (
"fmt"
"html"
"net/http"
"github.com/google/uuid"
)
func (this *Application) GET_Root(w http.ResponseWriter, r *http.Request) {
w.Header().Set(`Content-Type`, `text/html;charset=UTF-8`)
w.WriteHeader(200)
w.Write([]byte(`<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#040c3a">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🦙</text></svg>">
<title>` + html.EscapeString(AppTitle) + `</title>
<style type="text/css">
html {
font-family: sans-serif;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.banner {
height: 48px;
background: linear-gradient(#06638d, #040c3a);
color: white;
position: relative;
line-height: 48px;
vertical-align: middle;
}
.logo {
font-size: 18px;
padding-left: 8px;
}
.state-wrapper {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
pointer-events: none;
text-align: center;
}
#state {
display: none; /* inline-block; */
background: white;
color: black;
border: 2px solid black;
margin: 0 auto;
padding: 2px 4px;
opacity: 0.75;
font-size: 12px;
line-height: 18px;
vertical-align: middle;
transition: background-color 0.5s ease-out;
}
#state.alert {
background: lightyellow;
transition: initial;
}
.banner button {
float: right;
height: 32px;
margin: 8px 8px 8px 0;
}
textarea {
border: 0;
margin: 0;
height: calc(100% - 64px);
width: calc(100% - 16px);
padding: 8px 8px 4px 8px;
font-size: 16px; /* Prevent Safari autozoom */
resize: none;
outline: none;
box-shadow: none;
}
@media screen and (max-width: 400px) {
.logo {
font-size: 0;
}
.state-wrapper {
text-align: left;
margin-left: 8px;
}
}
</style>
<body>
<div class="banner">
<span class="logo">🦙 ` + html.EscapeString(AppTitle) + `</span>
<div class="state-wrapper">
<span id="state"></span>
</div>
<button id="generate">▶️ Generate</button>
<button id="interrupt" disabled>⏸️ Interrupt</button>
</div>
<textarea id="main" autofocus>A chat between a curious human and an artificial intelligence assistant.
The assistant gives helpful, detailed, and polite answers to the human's questions.
### Human: What is the capital city of New Zealand?
### Assistant:</textarea>
<script type="text/javascript">
function main() {
const conversationID = "` + uuid.New().String() + `";
const contextSize = ` + fmt.Sprintf("%d", ParamContextSize) + `;
const apiKey = "public-web-interface";
const $generate = document.getElementById("generate");
const $interrupt = document.getElementById("interrupt");
const $main = document.getElementById("main");
const $state = document.getElementById("state");
$main.setSelectionRange($main.value.length, $main.value.length);
$generate.addEventListener('click', async function() {
const content = $main.value;
if (content.split(" ").length >= (contextSize-4)) {
if (! confirm("Warning: high prompt length, the model will forget part of the content. Are you sure you want to continue?")) {
return;
}
}
$main.readOnly = true;
$generate.disabled = true;
try {
const controller = new AbortController();
$interrupt.disabled = false;
const doInterrupt = () => {
controller.abort();
$interrupt.removeEventListener('click', doInterrupt);
};
$interrupt.addEventListener('click', doInterrupt);
$state.style.display = "inline-block";
$state.textContent = "Waiting in queue..."
const response = await fetch("/api/v1/generate", {
method: "POST",
signal: controller.signal,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"ConversationID": conversationID,
"APIKey": apiKey,
"Content": content
})
});
$state.textContent = "The AI is reading your text so far..."
const reader = response.body.getReader();
const decoder = new TextDecoder();
for(;;) {
const singleReadResult = await reader.read();
if (singleReadResult.done) {
break;
}
state.textContent = "The AI is writing..."
$main.value += decoder.decode(singleReadResult.value);
$main.scrollTop = $main.scrollHeight;
$state.className = 'alert';
setTimeout(() => { $state.className = ''; }, 1);
}
$state.style.display = "none";
$state.textContent = ""
} catch (ex) {
$state.textContent = "Error";
alert(
"Error processing the request: " +
(ex instanceof Error ? ex.message : JSON.stringify(ex))
);
return;
} finally {
$main.readOnly = false;
$generate.disabled = false;
$interrupt.disabled = true;
}
});
}
main();
</script>
</body>
</html>
`))
}