216 lines
4.6 KiB
Go
216 lines
4.6 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">
|
|
<meta name="theme-color" content="#040c3a">
|
|
<title>` + html.EscapeString(AppTitle) + `</title>
|
|
<style type="text/css">
|
|
html {
|
|
font-family: sans-serif;
|
|
}
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
height: 100%;
|
|
|
|
position: relative;
|
|
}
|
|
.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;
|
|
}
|
|
.banner button {
|
|
float: right;
|
|
|
|
height: 32px;
|
|
margin: 8px 8px 8px 0;
|
|
}
|
|
textarea {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
top: 48px;
|
|
bottom: 0;
|
|
|
|
resize: none;
|
|
outline: none;
|
|
box-shadow: none;
|
|
|
|
border: 0;
|
|
background: #fff;
|
|
transition: background-color 0.5s ease-out;
|
|
}
|
|
textarea.alert {
|
|
background: lightyellow;
|
|
transition: initial;
|
|
}
|
|
|
|
@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;
|
|
|
|
$main.className = 'alert';
|
|
setTimeout(() => { $main.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>
|
|
`))
|
|
}
|