Skip to content

Commit 712ee17

Browse files
committed
small fixes
1 parent 6ea3315 commit 712ee17

File tree

2 files changed

+63
-41
lines changed

2 files changed

+63
-41
lines changed

examples/server/public/completion.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
const paramDefaults = {
22
stream: true,
3-
n_predict: 500,
43
temperature: 0.2,
5-
stop: ["</s>"]
64
};
75

86
let generation_settings = null;

examples/server/public/index.html

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@
77

88
<!-- Note: dependencies can de updated using ./deps.sh script -->
99
<link href="./deps_daisyui.min.css" rel="stylesheet" type="text/css" />
10-
<!-- Note for daisyui: because we're using a subset of daisyui via CDN, many things won't be included -->
1110
<script src="./deps_tailwindcss.js"></script>
1211
<style type="text/tailwindcss">
1312
.markdown {
1413
h1, h2, h3, h4, h5, h6, ul, ol, li { all: revert; }
1514
pre { @apply whitespace-pre-wrap; }
1615
/* TODO: fix markdown table */
1716
}
17+
/*
18+
Note for daisyui: because we're using a subset of daisyui via CDN, many things won't be included
19+
We can manually add the missing styles from https://cdnjs.cloudflare.com/ajax/libs/daisyui/4.12.14/full.css
20+
*/
1821
.bg-base-100 {background-color: var(--fallback-b1,oklch(var(--b1)/1))}
1922
.bg-base-200 {background-color: var(--fallback-b2,oklch(var(--b2)/1))}
2023
.bg-base-300 {background-color: var(--fallback-b3,oklch(var(--b3)/1))}
24+
.text-base-content {color: var(--fallback-bc,oklch(var(--bc)/1))}
2125
.btn-mini {
2226
@apply cursor-pointer opacity-0 group-hover:opacity-100 hover:shadow-md;
2327
}
@@ -26,8 +30,11 @@
2630

2731
<body>
2832
<div id="app" class="flex flex-row">
33+
<!-- sidebar -->
2934
<div class="flex flex-col bg-black bg-opacity-5 w-64 py-8 px-4 h-screen overflow-y-auto">
3035
<h2 class="font-bold mb-4 ml-4">Conversations</h2>
36+
37+
<!-- list of conversations -->
3138
<div :class="{
3239
'btn btn-ghost justify-start': true,
3340
'btn-active': messages.length === 0,
@@ -51,6 +58,8 @@ <h2 class="font-bold mb-4 ml-4">Conversations</h2>
5158
<div class="grow text-2xl font-bold mt-8 mb-6">
5259
🦙 llama.cpp - chat
5360
</div>
61+
62+
<!-- action buttons (top right) -->
5463
<div class="flex items-center">
5564
<button v-if="messages.length > 0" class="btn mr-1" @click="deleteConv(viewingConvId)" :disabled="isGenerating">
5665
<!-- delete conversation button -->
@@ -119,9 +128,8 @@ <h2 class="font-bold mb-4 ml-4">Conversations</h2>
119128
<!-- textarea for editing message -->
120129
<template v-if="editingMsg && editingMsg.id === msg.id">
121130
<textarea
122-
class="textarea textarea-bordered w-96"
123-
v-model="msg.content"
124-
@keydown.enter="editUserMsgAndRegenerate(msg)"></textarea>
131+
class="textarea textarea-bordered bg-base-100 text-base-content w-96"
132+
v-model="msg.content"></textarea>
125133
<br/>
126134
<button class="btn btn-ghost mt-2 mr-2" @click="editingMsg = null">Cancel</button>
127135
<button class="btn mt-2" @click="editUserMsgAndRegenerate(msg)">Submit</button>
@@ -147,7 +155,7 @@ <h2 class="font-bold mb-4 ml-4">Conversations</h2>
147155
</div>
148156
</div>
149157

150-
<!-- pending assistant message -->
158+
<!-- pending (ongoing) assistant message -->
151159
<div id="pending-msg" class="chat chat-start">
152160
<div v-if="pendingMsg" class="chat-bubble markdown">
153161
<span v-if="!pendingMsg.content" class="loading loading-dots loading-md"></span>
@@ -160,13 +168,14 @@ <h2 class="font-bold mb-4 ml-4">Conversations</h2>
160168
<div class="flex flex-row items-center mt-8 mb-6">
161169
<textarea
162170
class="textarea textarea-bordered w-full"
163-
placeholder="Type a message..."
171+
placeholder="Type a message (Shift+Enter to add a new line)"
164172
v-model="inputMsg"
165-
@keydown.enter="sendMessage"
173+
@keydown.enter.exact.prevent="sendMessage"
174+
@keydown.enter.shift.exact.prevent="inputMsg += '\n'"
166175
:disabled="isGenerating"
167176
id="msg-input"
168177
></textarea>
169-
<button v-if="!isGenerating" class="btn btn-primary ml-2" @click="sendMessage">Send</button>
178+
<button v-if="!isGenerating" class="btn btn-primary ml-2" @click="sendMessage" :disabled="inputMsg.length === 0">Send</button>
170179
<button v-else class="btn btn-neutral ml-2" @click="stopGeneration">Stop</button>
171180
</div>
172181
</div>
@@ -175,7 +184,7 @@ <h2 class="font-bold mb-4 ml-4">Conversations</h2>
175184
<dialog class="modal" :class="{'modal-open': showConfigDialog}">
176185
<div class="modal-box">
177186
<h3 class="text-lg font-bold mb-6">Settings</h3>
178-
<p class="opacity-40 mb-6">Settings below are store in browser's localStorage</p>
187+
<p class="opacity-40 mb-6">Settings below are saved in browser's localStorage</p>
179188
<label class="form-control mb-2">
180189
<div class="label">System Message</div>
181190
<textarea class="textarea textarea-bordered h-24" :placeholder="'Default: ' + configDefault.systemMessage" v-model="config.systemMessage"></textarea>
@@ -191,6 +200,8 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
191200
<div class="label inline">Custom JSON config (For more info, refer to <a class="underline" href="https://github.com/ggerganov/llama.cpp/blob/master/examples/server/README.md" target="_blank" rel="noopener noreferrer">server documentation</a>)</div>
192201
<textarea class="textarea textarea-bordered h-24" placeholder="Example: { &quot;mirostat&quot;: 1, &quot;min_p&quot;: 0.1 }" v-model="config.custom"></textarea>
193202
</label>
203+
204+
<!-- action buttons -->
194205
<button class="btn mr-4" @click="config = {...configDefault}">Reset to default</button>
195206
<button class="btn btn-primary" @click="closeSaveAndConfigDialog">Save and close</button>
196207
</div>
@@ -229,12 +240,12 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
229240
{ props: ["source", "options", "plugins"] }
230241
);
231242

232-
// storage class
233243
// coversations is stored in localStorage
234244
// format: { [convId]: { id: string, lastModified: number, messages: [...] } }
235245
// convId is a string prefixed with 'conv-'
236-
const Conversations = {
237-
getAll() {
246+
const StorageUtils = {
247+
// manage conversations
248+
getAllConversations() {
238249
const res = [];
239250
for (const key in localStorage) {
240251
if (key.startsWith('conv-')) {
@@ -245,13 +256,13 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
245256
return res;
246257
},
247258
// can return null if convId does not exist
248-
getOne(convId) {
259+
getOneConversation(convId) {
249260
return JSON.parse(localStorage.getItem(convId) || 'null');
250261
},
251262
// if convId does not exist, create one
252263
appendMsg(convId, msg) {
253264
if (msg.content === null) return;
254-
const conv = Conversations.getOne(convId) || {
265+
const conv = StorageUtils.getOneConversation(convId) || {
255266
id: convId,
256267
lastModified: Date.now(),
257268
messages: [],
@@ -267,12 +278,30 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
267278
localStorage.removeItem(convId);
268279
},
269280
filterAndKeepMsgs(convId, predicate) {
270-
const conv = Conversations.getOne(convId);
281+
const conv = StorageUtils.getOneConversation(convId);
271282
if (!conv) return;
272283
conv.messages = conv.messages.filter(predicate);
273284
conv.lastModified = Date.now();
274285
localStorage.setItem(convId, JSON.stringify(conv));
275286
},
287+
288+
// manage config
289+
getConfig() {
290+
return JSON.parse(localStorage.getItem('config') || 'null') || {...CONFIG_DEFAULT};
291+
},
292+
setConfig(config) {
293+
localStorage.setItem('config', JSON.stringify(config));
294+
},
295+
getTheme() {
296+
return localStorage.getItem('theme') || 'auto';
297+
},
298+
setTheme(theme) {
299+
if (theme === 'auto') {
300+
localStorage.removeItem('theme');
301+
} else {
302+
localStorage.setItem('theme', theme);
303+
}
304+
},
276305
};
277306

278307
// scroll to bottom of chat messages
@@ -287,15 +316,15 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
287316
},
288317
data() {
289318
return {
290-
conversations: Conversations.getAll(),
319+
conversations: StorageUtils.getAllConversations(),
291320
messages: [], // { id: number, role: 'user' | 'assistant', content: string }
292-
viewingConvId: Conversations.getNewConvId(),
321+
viewingConvId: StorageUtils.getNewConvId(),
293322
inputMsg: '',
294323
isGenerating: false,
295324
pendingMsg: null, // the on-going message from assistant
296325
stopGeneration: () => {},
297-
selectedTheme: localStorage.getItem('theme') || 'auto',
298-
config: JSON.parse(localStorage.getItem('config') || 'null') || {...CONFIG_DEFAULT},
326+
selectedTheme: StorageUtils.getTheme(),
327+
config: StorageUtils.getConfig(),
299328
showConfigDialog: false,
300329
editingMsg: null,
301330
// const
@@ -314,17 +343,12 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
314343
},
315344
methods: {
316345
setSelectedTheme(theme) {
317-
if (theme === 'auto') {
318-
this.selectedTheme = 'auto';
319-
localStorage.removeItem('theme');
320-
} else {
321-
this.selectedTheme = theme;
322-
localStorage.setItem('theme', theme);
323-
}
346+
this.selectedTheme = theme;
347+
StorageUtils.setTheme(theme);
324348
},
325349
newConversation() {
326350
if (this.isGenerating) return;
327-
this.viewingConvId = Conversations.getNewConvId();
351+
this.viewingConvId = StorageUtils.getNewConvId();
328352
this.editingMsg = null;
329353
this.fetchMessages();
330354
chatScrollToBottom();
@@ -339,9 +363,9 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
339363
deleteConv(convId) {
340364
if (this.isGenerating) return;
341365
if (window.confirm('Are you sure to delete this conversation?')) {
342-
Conversations.remove(convId);
366+
StorageUtils.remove(convId);
343367
if (this.viewingConvId === convId) {
344-
this.viewingConvId = Conversations.getNewConvId();
368+
this.viewingConvId = StorageUtils.getNewConvId();
345369
this.editingMsg = null;
346370
}
347371
this.fetchConversation();
@@ -362,13 +386,13 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
362386
}
363387
}
364388
this.showConfigDialog = false;
365-
localStorage.setItem('config', JSON.stringify(this.config));
389+
StorageUtils.setConfig(this.config);
366390
},
367391
async sendMessage() {
368392
if (!this.inputMsg) return;
369393
const currConvId = this.viewingConvId;
370394

371-
Conversations.appendMsg(currConvId, {
395+
StorageUtils.appendMsg(currConvId, {
372396
id: Date.now(),
373397
role: 'user',
374398
content: this.inputMsg,
@@ -419,14 +443,14 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
419443
}
420444
}
421445

422-
Conversations.appendMsg(currConvId, this.pendingMsg);
446+
StorageUtils.appendMsg(currConvId, this.pendingMsg);
423447
this.fetchConversation();
424448
this.fetchMessages();
425449
setTimeout(() => document.getElementById('msg-input').focus(), 1);
426450
} catch (error) {
427451
if (error.name === 'AbortError') {
428452
// user stopped the generation via stopGeneration() function
429-
Conversations.appendMsg(currConvId, this.pendingMsg);
453+
StorageUtils.appendMsg(currConvId, this.pendingMsg);
430454
this.fetchConversation();
431455
this.fetchMessages();
432456
} else {
@@ -444,9 +468,9 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
444468
// message actions
445469
regenerateMsg(msg) {
446470
if (this.isGenerating) return;
447-
// TODO: somehow keep old history (like how ChatGPT has different "tree")
471+
// TODO: somehow keep old history (like how ChatGPT has different "tree"). This can be done by adding "sub-conversations" with "subconv-" prefix, and new message will have a list of subconvIds
448472
const currConvId = this.viewingConvId;
449-
Conversations.filterAndKeepMsgs(currConvId, (m) => m.id < msg.id);
473+
StorageUtils.filterAndKeepMsgs(currConvId, (m) => m.id < msg.id);
450474
this.fetchConversation();
451475
this.fetchMessages();
452476
this.generateMessage(currConvId);
@@ -459,8 +483,8 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
459483
const currConvId = this.viewingConvId;
460484
const newContent = msg.content;
461485
this.editingMsg = null;
462-
Conversations.filterAndKeepMsgs(currConvId, (m) => m.id < msg.id);
463-
Conversations.appendMsg(currConvId, {
486+
StorageUtils.filterAndKeepMsgs(currConvId, (m) => m.id < msg.id);
487+
StorageUtils.appendMsg(currConvId, {
464488
id: Date.now(),
465489
role: 'user',
466490
content: newContent,
@@ -472,10 +496,10 @@ <h3 class="text-lg font-bold mb-6">Settings</h3>
472496

473497
// sync state functions
474498
fetchConversation() {
475-
this.conversations = Conversations.getAll();
499+
this.conversations = StorageUtils.getAllConversations();
476500
},
477501
fetchMessages() {
478-
this.messages = Conversations.getOne(this.viewingConvId)?.messages ?? [];
502+
this.messages = StorageUtils.getOneConversation(this.viewingConvId)?.messages ?? [];
479503
},
480504
},
481505
}).mount('#app');

0 commit comments

Comments
 (0)