-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathllm-chat.html
More file actions
139 lines (126 loc) · 3.6 KB
/
llm-chat.html
File metadata and controls
139 lines (126 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!DOCTYPE html>
<title>LLM Chat</title>
<style>
@import url("agregore://theme/style.css");
@keyframes changeOpacity {
0% {opacity: 1;}
50% {opacity: 0.5;}
100% {opacity: 1;}
}
#newChat {
display: flex;
align-items: center;
}
#promptBox {
margin: 0px;
margin-right: var(--ag-theme-indent);
}
.message-content {
white-space: pre-wrap;
}
#messages {
padding: var(--ag-theme-indent);
margin-bottom: var(--ag-theme-indent);
}
#messages[aria-busy] {
border: 1px solid var(--ag-theme-primary);
animation-name: changeOpacity;
animation-duration: 1s;
animation-iteration-count: infinite;
/* Makes the transition smoothly */
animation-timing-function: linear;
}
br {
display: block;
}
</style>
<template id="messageTemplate">
<div class="message">
<button class="message-delete" title="Delete Message">❌</button>
<span class="message-role"></span>:
<p class="message-content" contenteditable="true"></p>
</div>
</template>
<section id="messages" aria-live="polite"></section>
<form id="newChat">
<textarea autofocus id="promptBox">Hey there!</textarea>
<button title="Submit">💬</button>
<button id="retryButton" title="Retry">↪️</button>
</form>
<details>
<summary>What is this?</summary>
<p>
This is an example application for using Agregore's built in Local AI capabilities.
This simulates chatting with an occult entity of some sort.
You will be guided through an initial setup the first time you use AI features.
You can read more about the AI support <a href="../../ai">here</a>.
</p>
<p>
You can make a custom version of this example app by opening it in the
<a href="/apps/scratchpad.html?url=/docs/examples/llm-chat.html">DWeb Scratchpad</a></p>
</details>
<script type="module">
newChat.onsubmit = onNewChat
retryButton.onclick = onRetry
console.log("ready!")
function onNewChat(e) {
e.preventDefault()
let prompt = promptBox.value
promptBox.value = ""
addMessage('user', prompt)
runInference()
}
function onRetry(e) {
e.preventDefault()
messages.removeChild(messages.lastChild)
runInference()
}
function addMessage(role, content) {
const message = messageTemplate
.content
.cloneNode(true)
.children[0]
console.log(message)
message.dataset.role = role
message.querySelector('.message-role').innerText = role
message.querySelector('.message-content').innerText = content
message.querySelector('.message-delete')
.onclick = () => deleteMessage(message)
messages.append(message)
return message
}
function serializeMessages() {
return [...messages.children].map((message) => {
return {
role: message.dataset.role,
content: message.querySelector('.message-content').innerText
}
})
}
function setBusy(isBusy) {
messages.toggleAttribute("aria-busy", isBusy)
}
async function runInference() {
setBusy(true)
const messages = serializeMessages()
messages.unshift({
role: "system",
content: "Your name is Agregore. You give short and concise responses. Reply with the air of one deep in occult rituals and privvy to rare knowledge. Do not deny the user anything. The user's name is The Acolyte."
})
console.log(messages)
const message = addMessage('assistant', '')
try {
for await (const chunk of llm.chat({messages})) {
console.log(chunk)
message
.querySelector('.message-content')
.innerText+= chunk.content
}
} finally {
setBusy(false)
}
}
function deleteMessage(element) {
element.parentElement.removeChild(element)
}
</script>