-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathindex.html
141 lines (130 loc) · 6.97 KB
/
index.html
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
140
141
<!doctype html>
<html lang="en" class="h-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<title>OpenAI ChatGPT Demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"
integrity="sha256-4RctOgogjPAdwGbwq+rxfwAmSpZhWaafcZR9btzUk18=" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/cosmo/bootstrap.min.css"
integrity="sha256-axRDISYf7Hht1KhcMnfDV2nq7hD/8Q9Rxa0YlW/o3NU=" crossorigin="anonymous">
<link href="/static/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<main class="h-100 mh-100 d-flex flex-column overflow-hidden justify-content-start">
<div id="messages" class="px-4 pb-4 pt-2 flex-grow-1 overflow-y-auto overflow-x-hidden align-items-stretch">
<template id="message-template-user">
<div class="toast-container position-static w-100 d-flex flex-column align-items-stretch">
<div class="toast fade show w-75 rounded-3 align-self-end">
<div class="toast-header text-light background-user">
<i class="bi bi-person me-1" aria-hidden="true"></i>
<strong class="me-auto text-capitalize">
You
</strong>
</div>
<div class="toast-body message-content">
</div>
</div>
</div>
</template>
<template id="message-template-assistant">
<div class="toast-container position-static w-100 d-flex flex-column align-items-stretch">
<div class="toast fade show w-75 rounded-3 align-self-start">
<div class="toast-header text-light background-assistant">
<i class="bi bi-robot me-1" aria-hidden="true"></i>
<strong class="me-auto text-capitalize">
Assistant
</strong>
</div>
<div class="toast-body message-content">
<div class="loading-bar"></div>
<div class="thoughts" style="display:none;">
<details open>
<summary>💡 Thinking ...</summary>
<p class="thoughts-content"></p>
</details>
</div>
<div class="answer-content" style="background-color: white">
</div>
</div>
</div>
</div>
</template>
</div>
<div id="chat-area" class="text-light px-4 py-2 rounded-top-5 text-dark d-flex flex-column justify-content-center background-user">
<form id="chat-form">
<div class="input-group">
<i class="bi bi-body-text input-group-text" aria-hidden="true"></i>
<input id="message" name="message" class="form-control form-control-sm" type="text" rows="1" placeholder="<Your Message>" aria-label="Ask ChatGPT"></input>
<button type="submit" class="btn btn-outline-light">
Send
<i class="bi bi-send-fill" aria-hidden="true"></i>
</button>
</div>
</form>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/showdown.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ndjson-readablestream.umd.js"></script>
<script>
const form = document.getElementById("chat-form");
const messageInput = document.getElementById("message");
const targetContainer = document.getElementById("messages");
const userTemplate = document.querySelector('#message-template-user');
const assistantTemplate = document.querySelector('#message-template-assistant');
const converter = new showdown.Converter();
const messages = [];
form.addEventListener("submit", async function(e) {
e.preventDefault();
const message = messageInput.value;
const userTemplateClone = userTemplate.content.cloneNode(true);
userTemplateClone.querySelector(".message-content").innerText = message;
targetContainer.appendChild(userTemplateClone);
const assistantTemplateClone = assistantTemplate.content.cloneNode(true);
let messageDiv = assistantTemplateClone.querySelector(".message-content");
targetContainer.appendChild(assistantTemplateClone);
messages.push({
"role": "user",
"content": message
});
const response = await fetch("/chat/stream", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({messages: messages})
});
let answer = "";
let thoughts = "";
for await (const event of readNDJSONStream(response.body)) {
if (!event.delta) {
continue;
}
if (event.delta.reasoning_content) {
thoughts += event.delta.reasoning_content;
if (thoughts.trim().length > 0) {
// Only show thoughts if they are more than just whitespace
messageDiv.querySelector(".loading-bar").style.display = "none";
messageDiv.querySelector(".thoughts").style.display = "block";
messageDiv.querySelector(".thoughts-content").innerHTML = converter.makeHtml(thoughts);
}
} else {
messageDiv.querySelector(".loading-bar").style.display = "none";
answer += event.delta.content;
messageDiv.querySelector(".answer-content").innerHTML = converter.makeHtml(answer);
}
messageDiv.scrollIntoView();
if (event.error) {
messageDiv.innerHTML = "Error: " + event.error;
}
messages.push({
"role": "assistant",
"content": answer
});
messageInput.value = "";
}
});
</script>
</body>
</html>