From 69ecad21e7786ecbbdb4beb6f22b2bd5f5e478b4 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 17:36:16 +0530 Subject: [PATCH 01/64] SimpleChat: Add a skeletal html page Contains a div placeholder for showing chat messages till now a text-input for allowing user to enter next chat message/query to the model. a submit button to allow sending of the user entered message and chat till now to the model. --- examples/server/public/simplechat.html | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/server/public/simplechat.html diff --git a/examples/server/public/simplechat.html b/examples/server/public/simplechat.html new file mode 100644 index 0000000000000..dd6ccf92572a8 --- /dev/null +++ b/examples/server/public/simplechat.html @@ -0,0 +1,9 @@ + + Simple LlamaCPP Chat + +
+
+ + + + \ No newline at end of file From 0402a4b60e02f65e82ff6322e5a5114b834479ba Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 17:39:18 +0530 Subject: [PATCH 02/64] SimpleChat: A js skeleton with SimpleChat class Allows maintaining an array of chat message. Allows adding chat message (from any of the roles be it system, user, assistant, ...) Allows showing chat messages till now, in a given div element. --- examples/server/public/simplechat.js | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/server/public/simplechat.js diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js new file mode 100644 index 0000000000000..d0cfb6f8e82ce --- /dev/null +++ b/examples/server/public/simplechat.js @@ -0,0 +1,35 @@ +// @ts-check + +class SimpleChat { + + constructor() { + this.xchat = /** @type {{role: string, content: string}[]} */([]); + } + + /** + * Add an entry into xchat + * @param {string} role + * @param {string} content + */ + add(role, content) { + this.xchat.push( {role: role, content: content} ); + } + + /** + * Show the contents in the specified div + * @param {HTMLDivElement} div + * @param {boolean} bClear + */ + show(div, bClear=true) { + if (bClear) { + div.replaceChildren(); + } + for(const x of this.xchat) { + let entry = document.createElement("p"); + entry.innerText = `${x.role}: ${x.content}`; + div.appendChild(entry); + } + } + +} + From 1d3cc9353ab197838c05658d32cd251b3c08f10b Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 18:43:42 +0530 Subject: [PATCH 03/64] SimpleChat: request_json, globals, startme --- examples/server/public/simplechat.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index d0cfb6f8e82ce..e8c828ec5e477 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -3,7 +3,11 @@ class SimpleChat { constructor() { - this.xchat = /** @type {{role: string, content: string}[]} */([]); + /** + * Maintain in a form suitable for common LLM web service chat/completions' messages entry + * @type {{role: string, content: string}[]} + */ + this.xchat = []; } /** @@ -31,5 +35,23 @@ class SimpleChat { } } + request_json() { + let req = { + messages: this.xchat, + temperature: 0.7 + } + return JSON.stringify(req); + } + } + +let gChat = new SimpleChat(); +let gBaseURL = "http://127.0.0.1:8080"; +let gChatURL = `${gBaseURL}/chat/completions`; + + +function startme() { + let divChat = document.getElementById("chat"); + let btnSubmit = document.getElementById() +} From 70e58602645bbce55c614985083d7835e6812a7e Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 19:39:51 +0530 Subject: [PATCH 04/64] SimpleChatJS: Roles Class, submitClick Define Role class with static members corresponding to the roles. Update startme to * Get hold of the ui elements. * Attach a click handler to submit button, which adds the user input to xchats array and shows the chat messages till now in chat div element. Trap DOMContentLoaded to trigger startme --- examples/server/public/simplechat.js | 31 +++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index e8c828ec5e477..56ae29fd2ad47 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -1,5 +1,11 @@ // @ts-check +class Roles { + static System = "system"; + static User = "user"; + static Assistant = "assistant"; +} + class SimpleChat { constructor() { @@ -13,9 +19,12 @@ class SimpleChat { /** * Add an entry into xchat * @param {string} role - * @param {string} content + * @param {string|undefined|null} content */ add(role, content) { + if ((content == undefined) || (content == null) || (content == "")) { + return; + } this.xchat.push( {role: role, content: content} ); } @@ -52,6 +61,22 @@ let gChatURL = `${gBaseURL}/chat/completions`; function startme() { - let divChat = document.getElementById("chat"); - let btnSubmit = document.getElementById() + + let divChat = /** @type{HTMLDivElement} */(document.getElementById("chat")); + let btnSubmit = document.getElementById("submit"); + let inputUser = document.getElementById("user"); + + if (divChat == null) { + throw Error("ERRR:StartMe:Chat element missing"); + } + + btnSubmit?.addEventListener("click", (ev)=>{ + let content = inputUser?.textContent; + console.debug("DBUG:BtnSubmit:Click:", content) + gChat.add(Roles.User, content); + gChat.show(divChat); + }); + } + +document.addEventListener("DOMContentLoaded", startme); From 24d348ab97c2bc13f411ceef2bc9b2fbb1b8528f Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 19:44:43 +0530 Subject: [PATCH 05/64] SimpleChat:HTML: Bring in the js file --- examples/server/public/simplechat.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/server/public/simplechat.html b/examples/server/public/simplechat.html index dd6ccf92572a8..8426b384b4a96 100644 --- a/examples/server/public/simplechat.html +++ b/examples/server/public/simplechat.html @@ -1,5 +1,8 @@ - Simple LlamaCPP Chat + + Simple LlamaCPP Chat + +

From 256e02c7c9ab300f1fb3db666dcea650a3bca853 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 20:37:09 +0530 Subject: [PATCH 06/64] SimpleChat: Rather value wrt input text element --- examples/server/public/simplechat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index 56ae29fd2ad47..a22708b34ff04 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -64,14 +64,14 @@ function startme() { let divChat = /** @type{HTMLDivElement} */(document.getElementById("chat")); let btnSubmit = document.getElementById("submit"); - let inputUser = document.getElementById("user"); + let inputUser = /** @type{HTMLInputElement} */(document.getElementById("user")); if (divChat == null) { throw Error("ERRR:StartMe:Chat element missing"); } btnSubmit?.addEventListener("click", (ev)=>{ - let content = inputUser?.textContent; + let content = inputUser?.value; console.debug("DBUG:BtnSubmit:Click:", content) gChat.add(Roles.User, content); gChat.show(divChat); From 639d647ebf0f76b85e36cc1295c07058c6b9326f Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 20:48:03 +0530 Subject: [PATCH 07/64] SimpleChat: Also add completions related prompt --- examples/server/public/simplechat.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index a22708b34ff04..13be5eb3140fb 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -44,7 +44,7 @@ class SimpleChat { } } - request_json() { + request_messages_jsonstr() { let req = { messages: this.xchat, temperature: 0.7 @@ -52,6 +52,18 @@ class SimpleChat { return JSON.stringify(req); } + request_prompt_jsonstr() { + let prompt = ""; + for(const chat of this.xchat) { + prompt += `${chat.role}: ${chat.content}\n`; + } + let req = { + prompt: prompt, + temperature: 0.7 + } + return JSON.stringify(req); + } + } @@ -75,8 +87,11 @@ function startme() { console.debug("DBUG:BtnSubmit:Click:", content) gChat.add(Roles.User, content); gChat.show(divChat); + console.log("DBUG:BtnSubmit:Messages:", gChat.request_messages_jsonstr()); + console.log("DBUG:BtnSubmit:Messages:", gChat.request_prompt_jsonstr()); }); } + document.addEventListener("DOMContentLoaded", startme); From ce4aaeb692ef8b65a14de51eec87801373779520 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:00:16 +0530 Subject: [PATCH 08/64] SimpleChat: Use common helper logic wrt json data --- examples/server/public/simplechat.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index 13be5eb3140fb..b29e654090c17 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -44,14 +44,29 @@ class SimpleChat { } } + /** + * Add needed fields wrt json object to be sent wrt LLM web services completions endpoint + * Convert the json into string. + * @param {Object} obj + */ + request_jsonstr(obj) { + obj["temperature"] = 0.7; + return JSON.stringify(obj); + } + + /** + * Return a string form of json object suitable for chat/completions + */ request_messages_jsonstr() { let req = { messages: this.xchat, - temperature: 0.7 } - return JSON.stringify(req); + return this.request_jsonstr(req); } + /** + * Return a string form of json object suitable for /completions + */ request_prompt_jsonstr() { let prompt = ""; for(const chat of this.xchat) { @@ -59,9 +74,8 @@ class SimpleChat { } let req = { prompt: prompt, - temperature: 0.7 } - return JSON.stringify(req); + return this.request_jsonstr(req); } } From 27268a6067d6166c9bcc05848643d29fdd21e6dc Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:06:40 +0530 Subject: [PATCH 09/64] SimpleChat: Move handling of submit request into its own func --- examples/server/public/simplechat.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index b29e654090c17..96d403beb8e22 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -80,6 +80,20 @@ class SimpleChat { } +/** + * Handle submit request by user + * @param {HTMLInputElement} inputUser + * @param {HTMLDivElement} divChat + */ +function handle_submit(inputUser, divChat) { + let content = inputUser?.value; + console.debug("DBUG:BtnSubmit:Click:", content) + gChat.add(Roles.User, content); + gChat.show(divChat); + console.log("DBUG:BtnSubmit:Messages:", gChat.request_messages_jsonstr()); + console.log("DBUG:BtnSubmit:Messages:", gChat.request_prompt_jsonstr()); +} + let gChat = new SimpleChat(); let gBaseURL = "http://127.0.0.1:8080"; @@ -97,12 +111,7 @@ function startme() { } btnSubmit?.addEventListener("click", (ev)=>{ - let content = inputUser?.value; - console.debug("DBUG:BtnSubmit:Click:", content) - gChat.add(Roles.User, content); - gChat.show(divChat); - console.log("DBUG:BtnSubmit:Messages:", gChat.request_messages_jsonstr()); - console.log("DBUG:BtnSubmit:Messages:", gChat.request_prompt_jsonstr()); + handle_submit(inputUser, divChat); }); } From 33bc67baa61663ca06704eba2fd5311f07254081 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:15:08 +0530 Subject: [PATCH 10/64] SimpleChat: Try handshake with llm over its web service endpoint --- examples/server/public/simplechat.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index 96d403beb8e22..ad7d152b30739 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -84,14 +84,24 @@ class SimpleChat { * Handle submit request by user * @param {HTMLInputElement} inputUser * @param {HTMLDivElement} divChat + * @param {RequestInfo | URL} urlApi */ -function handle_submit(inputUser, divChat) { +async function handle_submit(inputUser, divChat, urlApi) { let content = inputUser?.value; console.debug("DBUG:BtnSubmit:Click:", content) gChat.add(Roles.User, content); gChat.show(divChat); console.log("DBUG:BtnSubmit:Messages:", gChat.request_messages_jsonstr()); console.log("DBUG:BtnSubmit:Messages:", gChat.request_prompt_jsonstr()); + inputUser.value = ""; + let resp = await fetch(urlApi, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: gChat.request_messages_jsonstr(), + }); + console.log("DBUG:HandleSubmit:Resp:", resp); } @@ -111,7 +121,7 @@ function startme() { } btnSubmit?.addEventListener("click", (ev)=>{ - handle_submit(inputUser, divChat); + handle_submit(inputUser, divChat, gChatURL); }); } From c6653479fc11372832e9958c8b6c01913d38c65b Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:30:10 +0530 Subject: [PATCH 11/64] SimpleChat:JS: Extract model response and show to user --- examples/server/public/simplechat.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index ad7d152b30739..87025158ba136 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -101,7 +101,11 @@ async function handle_submit(inputUser, divChat, urlApi) { }, body: gChat.request_messages_jsonstr(), }); - console.log("DBUG:HandleSubmit:Resp:", resp); + let respBody = await resp.json(); + console.log("DBUG:HandleSubmit:Resp:", respBody); + let assistantMsg = respBody["choices"][0]["message"]["content"]; + gChat.add(Roles.Assistant, assistantMsg); + gChat.show(divChat); } From 564469e4f6ca64fa2edafe2ae7280482676e9be2 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:36:30 +0530 Subject: [PATCH 12/64] SimpleChat:JS: Messages/Prompt, indicate working to end user --- examples/server/public/simplechat.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index 87025158ba136..effc6423b3b22 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -85,15 +85,21 @@ class SimpleChat { * @param {HTMLInputElement} inputUser * @param {HTMLDivElement} divChat * @param {RequestInfo | URL} urlApi + * @param {boolean} [bMessages] */ -async function handle_submit(inputUser, divChat, urlApi) { +async function handle_submit(inputUser, divChat, urlApi, bMessages=true) { let content = inputUser?.value; - console.debug("DBUG:BtnSubmit:Click:", content) gChat.add(Roles.User, content); gChat.show(divChat); - console.log("DBUG:BtnSubmit:Messages:", gChat.request_messages_jsonstr()); - console.log("DBUG:BtnSubmit:Messages:", gChat.request_prompt_jsonstr()); - inputUser.value = ""; + let theBody; + if (bMessages) { + theBody = gChat.request_messages_jsonstr(); + } else { + theBody = gChat.request_prompt_jsonstr(); + } + inputUser.value = "working..."; + inputUser.disabled = true; + console.debug("DBUG:HandleSubmit:ReqBody:", theBody); let resp = await fetch(urlApi, { method: "POST", headers: { @@ -101,8 +107,10 @@ async function handle_submit(inputUser, divChat, urlApi) { }, body: gChat.request_messages_jsonstr(), }); + inputUser.value = ""; + inputUser.disabled = false; let respBody = await resp.json(); - console.log("DBUG:HandleSubmit:Resp:", respBody); + console.log("DBUG:HandleSubmit:RespBody:", respBody); let assistantMsg = respBody["choices"][0]["message"]["content"]; gChat.add(Roles.Assistant, assistantMsg); gChat.show(divChat); From 7d772f6b9a52bfd48ab91b6dc037c3e50057282d Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 21:55:43 +0530 Subject: [PATCH 13/64] SimpleChat: Try keep input element in view --- examples/server/public/simplechat.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index effc6423b3b22..5f27c09bfc93d 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -97,6 +97,7 @@ async function handle_submit(inputUser, divChat, urlApi, bMessages=true) { } else { theBody = gChat.request_prompt_jsonstr(); } + inputUser.scrollIntoView(true); inputUser.value = "working..."; inputUser.disabled = true; console.debug("DBUG:HandleSubmit:ReqBody:", theBody); @@ -114,6 +115,7 @@ async function handle_submit(inputUser, divChat, urlApi, bMessages=true) { let assistantMsg = respBody["choices"][0]["message"]["content"]; gChat.add(Roles.Assistant, assistantMsg); gChat.show(divChat); + inputUser.scrollIntoView(true); } From 994285127334e3d8203521cfcc045960358a605a Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 22:12:40 +0530 Subject: [PATCH 14/64] SimpleChat: Diff user/assistant msgs, Make input wider Also show a default message to user Also add some metas --- examples/server/public/simplechat.html | 19 +++++++++++++++++-- examples/server/public/simplechat.js | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/examples/server/public/simplechat.html b/examples/server/public/simplechat.html index 8426b384b4a96..9f0ba98317662 100644 --- a/examples/server/public/simplechat.html +++ b/examples/server/public/simplechat.html @@ -1,12 +1,27 @@ Simple LlamaCPP Chat + + + + -
+

SimpleChat

+
+
+

Enter your text to the ai assistant below

+

- \ No newline at end of file + diff --git a/examples/server/public/simplechat.js b/examples/server/public/simplechat.js index 5f27c09bfc93d..9aa5bae38024e 100644 --- a/examples/server/public/simplechat.js +++ b/examples/server/public/simplechat.js @@ -1,4 +1,6 @@ // @ts-check +// A simple completions and chat/completions test related web front end logic +// by Humans for All class Roles { static System = "system"; @@ -39,6 +41,7 @@ class SimpleChat { } for(const x of this.xchat) { let entry = document.createElement("p"); + entry.className = `role-${x.role}`; entry.innerText = `${x.role}: ${x.content}`; div.appendChild(entry); } From ebe330d098dcc2ce6235d245286811652c1b2fe5 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 22:33:31 +0530 Subject: [PATCH 15/64] SimpleChat: Move into its own sub directory to avoid confusion --- examples/server/{public => public_simplechat}/simplechat.html | 0 examples/server/{public => public_simplechat}/simplechat.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/server/{public => public_simplechat}/simplechat.html (100%) rename examples/server/{public => public_simplechat}/simplechat.js (100%) diff --git a/examples/server/public/simplechat.html b/examples/server/public_simplechat/simplechat.html similarity index 100% rename from examples/server/public/simplechat.html rename to examples/server/public_simplechat/simplechat.html diff --git a/examples/server/public/simplechat.js b/examples/server/public_simplechat/simplechat.js similarity index 100% rename from examples/server/public/simplechat.js rename to examples/server/public_simplechat/simplechat.js From 29d2d22c02fb696cdf9b76d4e788f07db1b7da11 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 22:51:37 +0530 Subject: [PATCH 16/64] SimpleChat:sh: Add simple shell script to run python3 http.server So one needs to run the llm server locally then run this script and access it using a local browser --- examples/server/public_simplechat/simplechat.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 examples/server/public_simplechat/simplechat.sh diff --git a/examples/server/public_simplechat/simplechat.sh b/examples/server/public_simplechat/simplechat.sh new file mode 100755 index 0000000000000..a986fe71254df --- /dev/null +++ b/examples/server/public_simplechat/simplechat.sh @@ -0,0 +1,9 @@ + +PORT=$1 + +if [ "$PORT" == "" ]; then + PORT=9000 +fi + +echo "Open http://127.0.0.1:$PORT/simplechat.html in your local browser" +python3 -m http.server $PORT From e62087bf3fe81c9c904ad6d908e576f6c0f36332 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 23:01:03 +0530 Subject: [PATCH 17/64] SimpleChat:JS: Try trap enter key press wrt input text field So user can either press submit button or press enter key --- examples/server/public_simplechat/simplechat.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 9aa5bae38024e..ae6104ed82ef5 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -141,6 +141,13 @@ function startme() { handle_submit(inputUser, divChat, gChatURL); }); + inputUser?.addEventListener("keyup", (ev)=> { + if (ev.key === "Enter") { + btnSubmit?.click(); + ev.preventDefault(); + } + }); + } From 9feb58eaa58420812c48c152ee2b2a6d0d26ecd5 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 23:21:55 +0530 Subject: [PATCH 18/64] SimpleChat: Allow user to select chat or completion mode --- .../server/public_simplechat/simplechat.html | 8 +++++ .../server/public_simplechat/simplechat.js | 32 +++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 9f0ba98317662..83045e0d4e940 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -16,10 +16,18 @@

SimpleChat

+ + + +

Enter your text to the ai assistant below

+
diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index ae6104ed82ef5..4f7ad7c9e8383 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -8,6 +8,11 @@ class Roles { static Assistant = "assistant"; } +class ApiEP { + static Chat = "chat"; + static Completion = "completion"; +} + class SimpleChat { constructor() { @@ -87,30 +92,34 @@ class SimpleChat { * Handle submit request by user * @param {HTMLInputElement} inputUser * @param {HTMLDivElement} divChat - * @param {RequestInfo | URL} urlApi - * @param {boolean} [bMessages] + * @param {string} apiEP */ -async function handle_submit(inputUser, divChat, urlApi, bMessages=true) { +async function handle_submit(inputUser, divChat, apiEP) { + let content = inputUser?.value; gChat.add(Roles.User, content); gChat.show(divChat); + let theBody; - if (bMessages) { + let theUrl = gChatURL[apiEP] + if (apiEP == ApiEP.Chat) { theBody = gChat.request_messages_jsonstr(); } else { theBody = gChat.request_prompt_jsonstr(); } + inputUser.scrollIntoView(true); inputUser.value = "working..."; inputUser.disabled = true; - console.debug("DBUG:HandleSubmit:ReqBody:", theBody); - let resp = await fetch(urlApi, { + console.debug(`DBUG:HandleSubmit:${theUrl}:ReqBody:${theBody}`); + let resp = await fetch(theUrl, { method: "POST", headers: { "Content-Type": "application/json", }, - body: gChat.request_messages_jsonstr(), + body: theBody, }); + inputUser.value = ""; inputUser.disabled = false; let respBody = await resp.json(); @@ -119,12 +128,16 @@ async function handle_submit(inputUser, divChat, urlApi, bMessages=true) { gChat.add(Roles.Assistant, assistantMsg); gChat.show(divChat); inputUser.scrollIntoView(true); + } let gChat = new SimpleChat(); let gBaseURL = "http://127.0.0.1:8080"; -let gChatURL = `${gBaseURL}/chat/completions`; +let gChatURL = { + 'chat': `${gBaseURL}/chat/completions`, + 'completion': `${gBaseURL}/completions`, +} function startme() { @@ -132,13 +145,14 @@ function startme() { let divChat = /** @type{HTMLDivElement} */(document.getElementById("chat")); let btnSubmit = document.getElementById("submit"); let inputUser = /** @type{HTMLInputElement} */(document.getElementById("user")); + let selectApiEP = /** @type{HTMLInputElement} */(document.getElementById("api-ep")); if (divChat == null) { throw Error("ERRR:StartMe:Chat element missing"); } btnSubmit?.addEventListener("click", (ev)=>{ - handle_submit(inputUser, divChat, gChatURL); + handle_submit(inputUser, divChat, selectApiEP.value); }); inputUser?.addEventListener("keyup", (ev)=> { From 3e5edbacd67e32a8ca3fd97719f3b9de76164042 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Fri, 17 May 2024 23:36:10 +0530 Subject: [PATCH 19/64] SimpleChat: Dont submit if already submitted and waiting Also make chat the default selection wrt mode --- examples/server/public_simplechat/simplechat.html | 4 ++-- examples/server/public_simplechat/simplechat.js | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 83045e0d4e940..806f469fc067f 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -2,7 +2,7 @@ Simple LlamaCPP Chat - + -

SimpleChat

- - +
+ + +
+

SimpleChat

+
+ + +

Enter your text to the ai assistant below


- + From ae52ad1675bf590da5147c450edaea1252adda44 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 02:55:27 +0530 Subject: [PATCH 24/64] SimpleChat:Allow system prompt to be set, if provided before user --- examples/server/public_simplechat/simplechat.html | 1 + examples/server/public_simplechat/simplechat.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index f20b79c701fcd..1a645c7fd698a 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -40,6 +40,7 @@
+

Enter the system prompt above, before entering/submitting any user query

Enter your text to the ai assistant below

diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index bf5db259719ed..f1770ec9256db 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -90,11 +90,19 @@ class SimpleChat { /** * Handle submit request by user + * @param {HTMLInputElement} inputSystem * @param {HTMLInputElement} inputUser * @param {HTMLDivElement} divChat * @param {string} apiEP */ -async function handle_submit(inputUser, divChat, apiEP) { +async function handle_submit(inputSystem, inputUser, divChat, apiEP) { + + if (gChat.xchat.length == 0) { + let sysPrompt = inputSystem.value; + if (sysPrompt.length > 0) { + gChat.add(Roles.System, sysPrompt); + } + } let content = inputUser?.value; gChat.add(Roles.User, content); @@ -159,6 +167,7 @@ const gbCompletionFreshChatAlways = true; function startme() { + let inputSystem = /** @type{HTMLInputElement} */(document.getElementById("system")); let divChat = /** @type{HTMLDivElement} */(document.getElementById("chat")); let btnSubmit = document.getElementById("submit"); let inputUser = /** @type{HTMLInputElement} */(document.getElementById("user")); @@ -172,7 +181,7 @@ function startme() { if (inputUser.disabled) { return; } - handle_submit(inputUser, divChat, selectApiEP.value); + handle_submit(inputSystem, inputUser, divChat, selectApiEP.value); }); inputUser?.addEventListener("keyup", (ev)=> { From 884adfd739e8abcaeca3fbc6454b94189177faa3 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 03:07:40 +0530 Subject: [PATCH 25/64] SimpleChat: Ignore empty user input, without trimming --- examples/server/public_simplechat/simplechat.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index f1770ec9256db..35a74109ed011 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -30,9 +30,10 @@ class SimpleChat { */ add(role, content) { if ((content == undefined) || (content == null) || (content == "")) { - return; + return false; } this.xchat.push( {role: role, content: content} ); + return true; } /** @@ -105,7 +106,10 @@ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { } let content = inputUser?.value; - gChat.add(Roles.User, content); + if (!gChat.add(Roles.User, content)) { + console.debug("WARN:HandleSubmit:Ignoring empty user input..."); + return; + } gChat.show(divChat); let theBody; From 72151aa634b8f47bb88fabcac6de2418aeeda0dd Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 03:16:30 +0530 Subject: [PATCH 26/64] SimpleChat:Alert user if they provide sysprompt late or change it --- examples/server/public_simplechat/simplechat.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 35a74109ed011..1211628e60878 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -98,11 +98,21 @@ class SimpleChat { */ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { + let sysPrompt = inputSystem.value; if (gChat.xchat.length == 0) { - let sysPrompt = inputSystem.value; if (sysPrompt.length > 0) { gChat.add(Roles.System, sysPrompt); } + } else { + if (sysPrompt.length > 0) { + if (gChat.xchat[0].role !== Roles.System) { + console.error("ERRR:HandleSubmit:You need to specify system prompt before any user query, ignoring..."); + } else { + if (gChat.xchat[0].content !== sysPrompt) { + console.error("ERRR:HandleSubmit:You cant change system prompt, mid way through, ignoring..."); + } + } + } } let content = inputUser?.value; From 601fedf8c1b29cea1fbb2b6dd67e556c502f5454 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 03:19:59 +0530 Subject: [PATCH 27/64] SimpleChat: Move handling systemprompt into its own func --- .../server/public_simplechat/simplechat.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 1211628e60878..b208723feed7b 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -89,15 +89,12 @@ class SimpleChat { } + /** - * Handle submit request by user + * Handle setting of system prompt. * @param {HTMLInputElement} inputSystem - * @param {HTMLInputElement} inputUser - * @param {HTMLDivElement} divChat - * @param {string} apiEP */ -async function handle_submit(inputSystem, inputUser, divChat, apiEP) { - +function handle_systemprompt(inputSystem) { let sysPrompt = inputSystem.value; if (gChat.xchat.length == 0) { if (sysPrompt.length > 0) { @@ -114,6 +111,18 @@ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { } } } +} + +/** + * Handle submit request by user + * @param {HTMLInputElement} inputSystem + * @param {HTMLInputElement} inputUser + * @param {HTMLDivElement} divChat + * @param {string} apiEP + */ +async function handle_submit(inputSystem, inputUser, divChat, apiEP) { + + handle_systemprompt(inputSystem); let content = inputUser?.value; if (!gChat.add(Roles.User, content)) { From 0d0a28b4ab7c747ed767e66a52540105ef434ffe Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 03:31:37 +0530 Subject: [PATCH 28/64] SimpleChat:HTML: Add a style for system role message --- examples/server/public_simplechat/simplechat.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 1a645c7fd698a..f755e61577b2d 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -9,6 +9,9 @@ .heading { background-color: lightgray; } + .role-system { + background-color: lightblue; + } .role-user { background-color: lightgray; } From 65a56e6fdbca39537bc1745eeb06d41aa31b9a60 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 03:37:15 +0530 Subject: [PATCH 29/64] SimpleChat: Update the readme file --- examples/server/public_simplechat/readme.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index 4a9c92d038f8c..b5f180de83ddb 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -27,3 +27,14 @@ next run this web front end in examples/server/public_simplechat Open this simple web front end from your local browser as noted in the message printed when simplechat.sh is run * by default it is http://127.0.0.1:9000/simplechat.html +Once inside +* Select between chat and completion mode. By default it is set to chat mode. +* If you want to provide a system prompt, then enter it first, before entering any user query. + * you cant change the system prompt, after it is has been submitted once along with user query. + * you cant set a system prompt, after you have submitted any user query +* Enter your query and either press enter or click on the submit button +* Wait for the logic to communicate with the server and get the response. + * the user is not allowed to enter any fresh query during this time. + * the user input box will be disabled and a working message will be shown in it. +* just refresh the page, to reset wrt the chat history and or system prompt and start afresh. + From ebd5e71295b2df5ef7a015a1e8a128788bcde1ed Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 17:09:47 +0530 Subject: [PATCH 30/64] SimpleChat:CSS: Move style info into its own css file To keep it simple, clean and seperate so that things are not unnecessarily cluttered. --- .../server/public_simplechat/simplechat.css | 23 +++++++++++++++++++ .../server/public_simplechat/simplechat.html | 21 +---------------- 2 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 examples/server/public_simplechat/simplechat.css diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css new file mode 100644 index 0000000000000..da6357973a3a9 --- /dev/null +++ b/examples/server/public_simplechat/simplechat.css @@ -0,0 +1,23 @@ +/** + * the styling of the simplechat web frontend + * by Humans for All + */ + + .heading { + background-color: lightgray; +} +.role-system { + background-color: lightblue; +} +.role-user { + background-color: lightgray; +} +.wideinput { + width: 90vw; +} +.float-right { + float: right; +} +* { + margin: 0.4vh; +} diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index f755e61577b2d..5d5118b21f4a2 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -5,26 +5,7 @@ - + From a1a2f36a4580bd060c0873bcd95c3c35a9e5dd30 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 22:11:59 +0530 Subject: [PATCH 31/64] SimpleChat:CSS: Allow for chat div to be scrollable --- examples/server/public_simplechat/simplechat.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index da6357973a3a9..5c5ea48a4e309 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -18,6 +18,10 @@ .float-right { float: right; } +#chat { + height: 75vh; + overflow: scroll; +} * { margin: 0.4vh; } From a944ce7cbe809d1dd6ccbc8441efce23f7dad34c Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 22:21:29 +0530 Subject: [PATCH 32/64] SimpleChat:JS: Try ensure the last entry in chat is visible Needed because now only the chat div is scrollable and not the full page. In last commit the chat div size was fixed to 75% vertical height, so the full page no longer scrolls, so the old bring user-input element to view wont work, instead now the last element in the chat div should be brought into view. --- examples/server/public_simplechat/simplechat.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index b208723feed7b..fed5720c71b66 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -45,11 +45,16 @@ class SimpleChat { if (bClear) { div.replaceChildren(); } + let last = undefined; for(const x of this.xchat) { let entry = document.createElement("p"); entry.className = `role-${x.role}`; entry.innerText = `${x.role}: ${x.content}`; div.appendChild(entry); + last = entry; + } + if (last !== undefined) { + last.scrollIntoView(true); } } @@ -139,7 +144,6 @@ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { theBody = gChat.request_prompt_jsonstr(); } - inputUser.scrollIntoView(true); inputUser.value = "working..."; inputUser.disabled = true; console.debug(`DBUG:HandleSubmit:${theUrl}:ReqBody:${theBody}`); @@ -174,7 +178,6 @@ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { gChat.xchat.length = 0; } - inputUser.scrollIntoView(true); } From 6eb1e0fbde18305509d8190568bdb3edad796ad6 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 22:59:21 +0530 Subject: [PATCH 33/64] SimpleChat:JS: bottom of element visible, Set focus to user input As the generated text could be multiple lines and occupy more space that the full scrollable div's vertical space, make the bottom of the last element (which can be such a generated text) in the div visible by scrolling. Ensure that the user input box has focus --- examples/server/public_simplechat/simplechat.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index fed5720c71b66..d476dd69ebcea 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -54,7 +54,7 @@ class SimpleChat { last = entry; } if (last !== undefined) { - last.scrollIntoView(true); + last.scrollIntoView(false); } } @@ -178,6 +178,7 @@ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { gChat.xchat.length = 0; } + inputUser.focus(); } From 5a5f6ab848ef46c954ad75d4b0021e9b7d6f7963 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sat, 18 May 2024 23:12:41 +0530 Subject: [PATCH 34/64] SimpleChat: Update notes a bit. Try keep browser happy Avoid browser quirk mode with DOCTYPE. Help with accessibility a bit by specifying the language explicitly. Specify the char encoding explicitly, inturn utf-8 is a safe bet, even with intermixing of languages if reqd in future. Add a cache-control http-equiv meta tag, which in all probability will be ignored. Defer js loading and execution, just for fun and future, not that critical here as it stands now. --- examples/server/public_simplechat/readme.md | 13 ++++++++++++- examples/server/public_simplechat/simplechat.html | 8 ++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index b5f180de83ddb..6e671711be3ed 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -9,8 +9,11 @@ This simple web frontend, allows triggering/testing the server's /completions or in a simple way with minimal code from a common code base. And also allows trying to maintain a basic back and forth chatting to an extent. +User can set a system prompt, as well as try and chat with the model over a series of back and forth chat +messages. + NOTE: Given that the idea is for basic minimal testing, it doesnt bother with any model context length and -culling of old messages from the chat. Also currently I havent added input for a system prompt, but may add it. +culling of old messages from the chat. NOTE: It doesnt set any parameters other than temperature for now. However if someone wants they can update the js file as needed. @@ -38,3 +41,11 @@ Once inside * the user input box will be disabled and a working message will be shown in it. * just refresh the page, to reset wrt the chat history and or system prompt and start afresh. + +## Devel note + +Sometimes the browser may be stuborn with caching of the file, so your updates to html/css/js +may not be visible. Also remember that just refreshing/reloading page in browser or for that +matter clearing site data, dont directly override site caching in all cases. Worst case you may +have to change port. + diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 5d5118b21f4a2..b37ec84f34af7 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -1,10 +1,13 @@ - + + Simple LlamaCPP Chat + - + + @@ -26,6 +29,7 @@

Enter the system prompt above, before entering/submitting any user query

Enter your text to the ai assistant below

+

Refresh the page to start over fresh


From 676053fc7fa7eda5a7811f67c6ca43b585866967 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sun, 19 May 2024 02:52:33 +0530 Subject: [PATCH 35/64] SimpleChat:HTML:Group user input+btn together; Note about multichat --- examples/server/public_simplechat/readme.md | 5 +++++ examples/server/public_simplechat/simplechat.html | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index 6e671711be3ed..0b0649a0332a3 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -49,3 +49,8 @@ may not be visible. Also remember that just refreshing/reloading page in browser matter clearing site data, dont directly override site caching in all cases. Worst case you may have to change port. +Concept of multiple chat sessions with same or different system prompts, as well as saving and +restoring of those across browser usage sessions, can be woven around the SimpleChat class and +its instances relatively easily, however given the current goal of keeping this simple, it has +not been added, for now. + diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index b37ec84f34af7..1e82740f67188 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -33,7 +33,9 @@
- - +
+ + +
From 7905f2fcbe1ecb935e9eb1e43208d931de0a56a4 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sun, 19 May 2024 03:20:30 +0530 Subject: [PATCH 36/64] SimpleChat:JS: Allow for changing system prompt anytime for future --- .../server/public_simplechat/simplechat.js | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index d476dd69ebcea..d7cf61bc2e254 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -21,6 +21,7 @@ class SimpleChat { * @type {{role: string, content: string}[]} */ this.xchat = []; + this.iLastSys = -1; } /** @@ -33,6 +34,9 @@ class SimpleChat { return false; } this.xchat.push( {role: role, content: content} ); + if (role == Roles.System) { + this.iLastSys = this.xchat.length - 1; + } return true; } @@ -96,10 +100,10 @@ class SimpleChat { /** - * Handle setting of system prompt. + * Handle setting of system prompt, but only at begining. * @param {HTMLInputElement} inputSystem */ -function handle_systemprompt(inputSystem) { +function handle_systemprompt_begin(inputSystem) { let sysPrompt = inputSystem.value; if (gChat.xchat.length == 0) { if (sysPrompt.length > 0) { @@ -118,6 +122,29 @@ function handle_systemprompt(inputSystem) { } } +/** + * Handle setting of system prompt, at any time. + * @param {HTMLInputElement} inputSystem + */ +function handle_systemprompt_anytime(inputSystem) { + let sysPrompt = inputSystem.value; + if (sysPrompt.length <= 0) { + return; + } + + if (gChat.iLastSys < 0) { + gChat.add(Roles.System, sysPrompt); + return; + } + + let lastSys = gChat.xchat[gChat.iLastSys].content; + if (lastSys !== sysPrompt) { + gChat.add(Roles.System, sysPrompt); + return; + } +} + + /** * Handle submit request by user * @param {HTMLInputElement} inputSystem @@ -127,7 +154,7 @@ function handle_systemprompt(inputSystem) { */ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { - handle_systemprompt(inputSystem); + handle_systemprompt_anytime(inputSystem); let content = inputUser?.value; if (!gChat.add(Roles.User, content)) { From 5976126c26d116c559187ca616c49107a37f5fc0 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sun, 19 May 2024 03:42:44 +0530 Subject: [PATCH 37/64] SimpleChat:Readme: Note about handle_systemprompt begin/anytime --- examples/server/public_simplechat/readme.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index 0b0649a0332a3..860892d4e36b0 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -32,9 +32,14 @@ Open this simple web front end from your local browser as noted in the message p Once inside * Select between chat and completion mode. By default it is set to chat mode. -* If you want to provide a system prompt, then enter it first, before entering any user query. - * you cant change the system prompt, after it is has been submitted once along with user query. - * you cant set a system prompt, after you have submitted any user query +* If you want to provide a system prompt, then ideally enter it first, before entering any user query. + * if handle_systemprompt_begin is used + * you cant change the system prompt, after it is has been submitted once along with user query. + * you cant set a system prompt, after you have submitted any user query + * if handle_systemprompt_anytime is used + * one can change the system prompt any time during chat, by changing the contents of system prompt. + * inturn the updated/changed system prompt will be inserted into the chat session. + * this allows for the subsequent user chatting to be driven by the new system prompt set above. * Enter your query and either press enter or click on the submit button * Wait for the logic to communicate with the server and get the response. * the user is not allowed to enter any fresh query during this time. @@ -54,3 +59,5 @@ restoring of those across browser usage sessions, can be woven around the Simple its instances relatively easily, however given the current goal of keeping this simple, it has not been added, for now. +By switching between handle_systemprompt_begin/anytime, one can control whether one can change +the system prompt, anytime during the conversation or only at the beginning. From c191e475d592467e4322a7428800ea4d69f915f5 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Sun, 19 May 2024 15:51:07 +0530 Subject: [PATCH 38/64] SimpleChat:HTML: Add viewport meta for better mobile friendliness Without this the page content may look too small. --- examples/server/public_simplechat/simplechat.html | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 1e82740f67188..908bd74bd2ba1 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -3,6 +3,7 @@ Simple LlamaCPP Chat + From c88088c7a1c17c12ece622098e05345aa050dffc Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 10:40:50 +0530 Subject: [PATCH 39/64] SimpleChat:HtmlCss: Cleanup UI flow set margin wrt vmin rather than vw or vh so portrait/landscape ok. Use flex and flex-grow to put things on the same line as well as distribute available space as needed. Given two main elements/line so it remains simple. In each line have one element with grows and one sits with a basic comfortably fixed size. --- .../server/public_simplechat/simplechat.css | 13 +++++++--- .../server/public_simplechat/simplechat.html | 24 ++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index 5c5ea48a4e309..f7ea6ec230616 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -12,8 +12,8 @@ .role-user { background-color: lightgray; } -.wideinput { - width: 90vw; +.flex-grow { + flex-grow: 1; } .float-right { float: right; @@ -22,6 +22,13 @@ height: 75vh; overflow: scroll; } +button { + min-width: 8vw; +} +.sameline { + display: flex; + flex-direction: row; +} * { - margin: 0.4vh; + margin: 0.6vmin; } diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 908bd74bd2ba1..4bfcadb0153ab 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -13,18 +13,20 @@ -
- - +
+

SimpleChat

+
+ + +
-

SimpleChat

-
+
- +

@@ -34,8 +36,8 @@

-
- +
+
From dfadac7813500a9050991ccd33fcf375610692ee Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 11:56:41 +0530 Subject: [PATCH 40/64] SimpleChat: textarea for multiline user chat, inturn shift+enter 4 enter --- examples/server/public_simplechat/simplechat.html | 9 +++++---- examples/server/public_simplechat/simplechat.js | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 4bfcadb0153ab..85cc734543c62 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -30,14 +30,15 @@

-

Enter the system prompt above, before entering/submitting any user query

-

Enter your text to the ai assistant below

-

Refresh the page to start over fresh

+

Enter the system prompt above, before entering/submitting any user query.

+

Enter your text to the ai assistant below.

+

Use shift+enter for inserting enter.

+

Refresh the page to start over fresh.


- +
diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index d7cf61bc2e254..5e73c204c09db 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -239,7 +239,9 @@ function startme() { }); inputUser?.addEventListener("keyup", (ev)=> { - if (ev.key === "Enter") { + // allow user to insert enter into their message using shift+enter. + // while just pressing enter key will lead to submitting. + if ((ev.key === "Enter") && (!ev.shiftKey)) { btnSubmit?.click(); ev.preventDefault(); } From 6597fafeae64d8bfdc3cb4a05fab2b14e140719b Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 16:13:24 +0530 Subject: [PATCH 41/64] SimpleChat: Make vertical layout better responsive (flex based) Also needed to make things cleaner and properly usable whether landscape or portrait, after changing to multiline textarea rather than single line user input. Avoid hardcoding the chat-till-now display area height, instead make it a flex-growable within a flex column of ui elements within a fixed vertical area. --- examples/server/public_simplechat/readme.md | 4 ++ .../server/public_simplechat/simplechat.css | 19 ++++++- .../server/public_simplechat/simplechat.html | 50 ++++++++++--------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index 860892d4e36b0..caf34b5f53149 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -12,12 +12,16 @@ and forth chatting to an extent. User can set a system prompt, as well as try and chat with the model over a series of back and forth chat messages. +The UI follows a responsive web design so that the layout can adapt to available display space in a usable +enough manner, in general. + NOTE: Given that the idea is for basic minimal testing, it doesnt bother with any model context length and culling of old messages from the chat. NOTE: It doesnt set any parameters other than temperature for now. However if someone wants they can update the js file as needed. + ## usage first run examples/server diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index f7ea6ec230616..cee6112674cf1 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -3,32 +3,47 @@ * by Humans for All */ - .heading { +#fullbody { + height: 98vh; +} + +.heading { background-color: lightgray; } + .role-system { background-color: lightblue; } .role-user { background-color: lightgray; } + .flex-grow { flex-grow: 1; } .float-right { float: right; } + #chat { - height: 75vh; overflow: scroll; + flex-grow: 1; + flex-shrink: 1; + min-height: 40vh; } button { min-width: 8vw; } + .sameline { display: flex; flex-direction: row; } +.samecolumn { + display: flex; + flex-direction: column; +} + * { margin: 0.6vmin; } diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/simplechat.html index 85cc734543c62..b7684193895e3 100644 --- a/examples/server/public_simplechat/simplechat.html +++ b/examples/server/public_simplechat/simplechat.html @@ -12,34 +12,38 @@ +
-
-

SimpleChat

- - +

SimpleChat

+
+ + +
-
-
- - -
-
-
-

Enter the system prompt above, before entering/submitting any user query.

-

Enter your text to the ai assistant below.

-

Use shift+enter for inserting enter.

-

Refresh the page to start over fresh.

-
+
+ + +
+ +
+
+

Enter the system prompt above, before entering/submitting any user query.

+

Enter your text to the ai assistant below.

+

Use shift+enter for inserting enter.

+

Refresh the page to start over fresh.

+
+ +
+
+ + +
-
-
- -
From e5000cdb832e32def50656bc7a02600be3216c38 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 18:18:23 +0530 Subject: [PATCH 42/64] SimpleChat: Rename simplechat.html to index.html, update readme Instead of providing a seperate shell script, update the readme wrt how to run/use this web front end. --- .../{simplechat.html => index.html} | 0 examples/server/public_simplechat/readme.md | 26 ++++++++++++++----- .../server/public_simplechat/simplechat.sh | 9 ------- 3 files changed, 20 insertions(+), 15 deletions(-) rename examples/server/public_simplechat/{simplechat.html => index.html} (100%) delete mode 100755 examples/server/public_simplechat/simplechat.sh diff --git a/examples/server/public_simplechat/simplechat.html b/examples/server/public_simplechat/index.html similarity index 100% rename from examples/server/public_simplechat/simplechat.html rename to examples/server/public_simplechat/index.html diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index caf34b5f53149..0f6a1cee069e0 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -3,6 +3,7 @@ by Humans for All. + ## overview This simple web frontend, allows triggering/testing the server's /completions or /chat/completions endpoints @@ -24,15 +25,27 @@ the js file as needed. ## usage +One could run this web frontend directly using server itself or if anyone is thinking of adding a built in web +frontend to configure the server over http(s) or so, then run this web frontend using something like python's +http module. + +### running using examples/server + +bin/server -m path/model.gguf --path ../examples/server/public_simplechat [--port PORT] + +### running using python3's server module + first run examples/server * bin/server -m path/model.gguf next run this web front end in examples/server/public_simplechat -* ./simplechat.sh -* this uses python3's http.server to host this web front end +* cd ../examples/server/public_simplechat +* python3 -m http.server PORT + +### using the front end -Open this simple web front end from your local browser as noted in the message printed when simplechat.sh is run -* by default it is http://127.0.0.1:9000/simplechat.html +Open this simple web front end from your local browser +* http://127.0.0.1:PORT/index.html Once inside * Select between chat and completion mode. By default it is set to chat mode. @@ -44,7 +57,8 @@ Once inside * one can change the system prompt any time during chat, by changing the contents of system prompt. * inturn the updated/changed system prompt will be inserted into the chat session. * this allows for the subsequent user chatting to be driven by the new system prompt set above. -* Enter your query and either press enter or click on the submit button +* Enter your query and either press enter or click on the submit button. + If you want to insert enter (\n) as part of your chat/query to ai model, use shift+enter. * Wait for the logic to communicate with the server and get the response. * the user is not allowed to enter any fresh query during this time. * the user input box will be disabled and a working message will be shown in it. @@ -56,7 +70,7 @@ Once inside Sometimes the browser may be stuborn with caching of the file, so your updates to html/css/js may not be visible. Also remember that just refreshing/reloading page in browser or for that matter clearing site data, dont directly override site caching in all cases. Worst case you may -have to change port. +have to change port. Or in dev tools of browser, you may be able to disable caching fully. Concept of multiple chat sessions with same or different system prompts, as well as saving and restoring of those across browser usage sessions, can be woven around the SimpleChat class and diff --git a/examples/server/public_simplechat/simplechat.sh b/examples/server/public_simplechat/simplechat.sh deleted file mode 100755 index a986fe71254df..0000000000000 --- a/examples/server/public_simplechat/simplechat.sh +++ /dev/null @@ -1,9 +0,0 @@ - -PORT=$1 - -if [ "$PORT" == "" ]; then - PORT=9000 -fi - -echo "Open http://127.0.0.1:$PORT/simplechat.html in your local browser" -python3 -m http.server $PORT From 3fc607f8320d00fb523ddeec552407e807b55dd1 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 21:27:39 +0530 Subject: [PATCH 43/64] SimpleChat: Screen fixed view and scrolling, Printing full --- examples/server/public_simplechat/simplechat.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index cee6112674cf1..4797dd9b82713 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -47,3 +47,11 @@ button { * { margin: 0.6vmin; } + +@media print { + + #fullbody { + height: auto; + } + +} From af621975bbc47d0584536d5842011d87d53254b1 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 21:34:48 +0530 Subject: [PATCH 44/64] SimpleChat:JS:CI: Avoid space at end of jsdoc param line --- examples/server/public_simplechat/simplechat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 5e73c204c09db..faf6ba6b489ee 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -42,8 +42,8 @@ class SimpleChat { /** * Show the contents in the specified div - * @param {HTMLDivElement} div - * @param {boolean} bClear + * @param {HTMLDivElement} div + * @param {boolean} bClear */ show(div, bClear=true) { if (bClear) { From 9b97feab45e450415511608636db0871784412b4 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 22:38:36 +0530 Subject: [PATCH 45/64] SimpleChat:JS: MultiChat initial skeleton Will help maintain multiple independent chats in future --- .../server/public_simplechat/simplechat.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index faf6ba6b489ee..e41f02e5f5152 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -218,6 +218,29 @@ let gChatURL = { } const gbCompletionFreshChatAlways = true; +class MultiChat { + + constructor() { + /** @type {number} */ + this.iChat = -1; + /** @type {SimpleChat[]} */ + this.simpleChats = []; + /** @type {string[]} */ + this.baseURLs = []; + } + + /** + * Start a new chat + * @param {string} baseURL + */ + new_chat(baseURL) { + this.simpleChats.push(new SimpleChat()); + this.baseURLs.push(baseURL); + this.iChat = this.simpleChats.length - 1; + } + +} + function startme() { From 5c1a9f4d8b89d0a9107684565285721f9fc7b36e Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 22:59:32 +0530 Subject: [PATCH 46/64] SimpleChat:JS: Move system prompt begin/anytime into SimpleChat --- .../server/public_simplechat/simplechat.js | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index e41f02e5f5152..12541345d2ad2 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -96,55 +96,55 @@ class SimpleChat { return this.request_jsonstr(req); } -} - - -/** - * Handle setting of system prompt, but only at begining. - * @param {HTMLInputElement} inputSystem - */ -function handle_systemprompt_begin(inputSystem) { - let sysPrompt = inputSystem.value; - if (gChat.xchat.length == 0) { - if (sysPrompt.length > 0) { - gChat.add(Roles.System, sysPrompt); - } - } else { - if (sysPrompt.length > 0) { - if (gChat.xchat[0].role !== Roles.System) { - console.error("ERRR:HandleSubmit:You need to specify system prompt before any user query, ignoring..."); - } else { - if (gChat.xchat[0].content !== sysPrompt) { - console.error("ERRR:HandleSubmit:You cant change system prompt, mid way through, ignoring..."); + /** + * Allow setting of system prompt, but only at begining. + * @param {string} sysPrompt + * @param {string} msgTag + */ + add_system_begin(sysPrompt, msgTag) { + if (this.xchat.length == 0) { + if (sysPrompt.length > 0) { + return this.add(Roles.System, sysPrompt); + } + } else { + if (sysPrompt.length > 0) { + if (this.xchat[0].role !== Roles.System) { + console.error(`ERRR:SimpleChat:${msgTag}:You need to specify system prompt before any user query, ignoring...`); + } else { + if (this.xchat[0].content !== sysPrompt) { + console.error(`ERRR:SimpleChat:${msgTag}:You cant change system prompt, mid way through, ignoring...`); + } } } } + return false; } -} -/** - * Handle setting of system prompt, at any time. - * @param {HTMLInputElement} inputSystem - */ -function handle_systemprompt_anytime(inputSystem) { - let sysPrompt = inputSystem.value; - if (sysPrompt.length <= 0) { - return; - } + /** + * Allow setting of system prompt, at any time. + * @param {string} sysPrompt + * @param {string} msgTag + */ + add_system_anytime(sysPrompt, msgTag) { + if (sysPrompt.length <= 0) { + return false; + } - if (gChat.iLastSys < 0) { - gChat.add(Roles.System, sysPrompt); - return; - } + if (this.iLastSys < 0) { + return this.add(Roles.System, sysPrompt); + } - let lastSys = gChat.xchat[gChat.iLastSys].content; - if (lastSys !== sysPrompt) { - gChat.add(Roles.System, sysPrompt); - return; + let lastSys = this.xchat[this.iLastSys].content; + if (lastSys !== sysPrompt) { + return this.add(Roles.System, sysPrompt); + } + return false; } + } + /** * Handle submit request by user * @param {HTMLInputElement} inputSystem @@ -154,7 +154,7 @@ function handle_systemprompt_anytime(inputSystem) { */ async function handle_submit(inputSystem, inputUser, divChat, apiEP) { - handle_systemprompt_anytime(inputSystem); + gChat.add_system_anytime(inputSystem.value, "0"); let content = inputUser?.value; if (!gChat.add(Roles.User, content)) { From fcf2af950439c75c3269e2cc24b5fd0443af614c Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 23:21:04 +0530 Subject: [PATCH 47/64] SimpleChat:JS:Keep MultiChatUI simple for now Worry about different chats with different servers for later. --- examples/server/public_simplechat/simplechat.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 12541345d2ad2..507eef7313a76 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -218,24 +218,20 @@ let gChatURL = { } const gbCompletionFreshChatAlways = true; -class MultiChat { +class MultiChatUI { constructor() { /** @type {number} */ this.iChat = -1; /** @type {SimpleChat[]} */ this.simpleChats = []; - /** @type {string[]} */ - this.baseURLs = []; } /** * Start a new chat - * @param {string} baseURL */ - new_chat(baseURL) { + new_chat() { this.simpleChats.push(new SimpleChat()); - this.baseURLs.push(baseURL); this.iChat = this.simpleChats.length - 1; } From 8ef1aa97a668a014f5a82300d5a95a9e5c6eed86 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Mon, 20 May 2024 23:43:51 +0530 Subject: [PATCH 48/64] SimpleChat:JS: Move handle submit into MultiChat, build on same Create an instance of MultiChatUI and inturn a instance of chat session, which is what the UI will inturn work on. --- .../server/public_simplechat/simplechat.js | 142 +++++++++--------- 1 file changed, 73 insertions(+), 69 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 507eef7313a76..6bea04725a491 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -144,73 +144,6 @@ class SimpleChat { } - -/** - * Handle submit request by user - * @param {HTMLInputElement} inputSystem - * @param {HTMLInputElement} inputUser - * @param {HTMLDivElement} divChat - * @param {string} apiEP - */ -async function handle_submit(inputSystem, inputUser, divChat, apiEP) { - - gChat.add_system_anytime(inputSystem.value, "0"); - - let content = inputUser?.value; - if (!gChat.add(Roles.User, content)) { - console.debug("WARN:HandleSubmit:Ignoring empty user input..."); - return; - } - gChat.show(divChat); - - let theBody; - let theUrl = gChatURL[apiEP] - if (apiEP == ApiEP.Chat) { - theBody = gChat.request_messages_jsonstr(); - } else { - theBody = gChat.request_prompt_jsonstr(); - } - - inputUser.value = "working..."; - inputUser.disabled = true; - console.debug(`DBUG:HandleSubmit:${theUrl}:ReqBody:${theBody}`); - let resp = await fetch(theUrl, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: theBody, - }); - - inputUser.value = ""; - inputUser.disabled = false; - let respBody = await resp.json(); - console.debug("DBUG:HandleSubmit:RespBody:", respBody); - let assistantMsg; - if (apiEP == ApiEP.Chat) { - assistantMsg = respBody["choices"][0]["message"]["content"]; - } else { - try { - assistantMsg = respBody["choices"][0]["text"]; - } catch { - assistantMsg = respBody["content"]; - } - } - gChat.add(Roles.Assistant, assistantMsg); - gChat.show(divChat); - // Purposefully clear at end rather than begin of this function - // so that one can switch from chat to completion mode and sequece - // in a completion mode with multiple user-assistant chat data - // from before to be sent/occur once. - if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { - gChat.xchat.length = 0; - } - inputUser.focus(); - -} - - -let gChat = new SimpleChat(); let gBaseURL = "http://127.0.0.1:8080"; let gChatURL = { 'chat': `${gBaseURL}/chat/completions`, @@ -218,6 +151,7 @@ let gChatURL = { } const gbCompletionFreshChatAlways = true; + class MultiChatUI { constructor() { @@ -228,16 +162,84 @@ class MultiChatUI { } /** - * Start a new chat + * Start a new chat session */ new_chat() { this.simpleChats.push(new SimpleChat()); this.iChat = this.simpleChats.length - 1; } + /** + * Handle user query submit request, wrt current chat session. + * @param {HTMLInputElement} inputSystem + * @param {HTMLInputElement} inputUser + * @param {HTMLDivElement} divChat + * @param {string} apiEP + */ + async handle_user_submit(inputSystem, inputUser, divChat, apiEP) { + + let chat = this.simpleChats[this.iChat]; + + chat.add_system_anytime(inputSystem.value, "0"); + + let content = inputUser.value; + if (!chat.add(Roles.User, content)) { + console.debug("WARN:MCUI:HandleUserSubmit:Ignoring empty user input..."); + return; + } + chat.show(divChat); + + let theBody; + let theUrl = gChatURL[apiEP] + if (apiEP == ApiEP.Chat) { + theBody = chat.request_messages_jsonstr(); + } else { + theBody = chat.request_prompt_jsonstr(); + } + + inputUser.value = "working..."; + inputUser.disabled = true; + console.debug(`DBUG:MCUI:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); + let resp = await fetch(theUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: theBody, + }); + + inputUser.value = ""; + inputUser.disabled = false; + let respBody = await resp.json(); + console.debug("DBUG:MCUI:HandleUserSubmit:RespBody:", respBody); + let assistantMsg; + if (apiEP == ApiEP.Chat) { + assistantMsg = respBody["choices"][0]["message"]["content"]; + } else { + try { + assistantMsg = respBody["choices"][0]["text"]; + } catch { + assistantMsg = respBody["content"]; + } + } + chat.add(Roles.Assistant, assistantMsg); + chat.show(divChat); + // Purposefully clear at end rather than begin of this function + // so that one can switch from chat to completion mode and sequece + // in a completion mode with multiple user-assistant chat data + // from before to be sent/occur once. + if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { + chat.xchat.length = 0; + } + inputUser.focus(); + } + } +let gMuitChat = new MultiChatUI(); + + function startme() { let inputSystem = /** @type{HTMLInputElement} */(document.getElementById("system")); @@ -250,11 +252,13 @@ function startme() { throw Error("ERRR:StartMe:Chat element missing"); } + gMuitChat.new_chat(); + btnSubmit?.addEventListener("click", (ev)=>{ if (inputUser.disabled) { return; } - handle_submit(inputSystem, inputUser, divChat, selectApiEP.value); + gMuitChat.handle_user_submit(inputSystem, inputUser, divChat, selectApiEP.value); }); inputUser?.addEventListener("keyup", (ev)=> { From 7be6aeb6d62301a602fcbdb9ceac500aa7f69d2a Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 00:18:58 +0530 Subject: [PATCH 49/64] SimpleChat:JS: Move to dictionary of SimpleChat, instead of array --- .../server/public_simplechat/simplechat.js | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 6bea04725a491..4cd2fcecc0bc0 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -155,36 +155,35 @@ const gbCompletionFreshChatAlways = true; class MultiChatUI { constructor() { - /** @type {number} */ - this.iChat = -1; - /** @type {SimpleChat[]} */ - this.simpleChats = []; + /** @type {Object} */ + this.simpleChats = {}; } /** * Start a new chat session + * @param {string} chatId */ - new_chat() { - this.simpleChats.push(new SimpleChat()); - this.iChat = this.simpleChats.length - 1; + new_chat(chatId) { + this.simpleChats[chatId] = new SimpleChat(); } /** - * Handle user query submit request, wrt current chat session. + * Handle user query submit request, wrt specified chat session. + * @param {string} chatId * @param {HTMLInputElement} inputSystem * @param {HTMLInputElement} inputUser * @param {HTMLDivElement} divChat * @param {string} apiEP */ - async handle_user_submit(inputSystem, inputUser, divChat, apiEP) { + async handle_user_submit(chatId, inputSystem, inputUser, divChat, apiEP) { - let chat = this.simpleChats[this.iChat]; + let chat = this.simpleChats[chatId]; - chat.add_system_anytime(inputSystem.value, "0"); + chat.add_system_anytime(inputSystem.value, chatId); let content = inputUser.value; if (!chat.add(Roles.User, content)) { - console.debug("WARN:MCUI:HandleUserSubmit:Ignoring empty user input..."); + console.debug(`WARN:MCUI:${chatId}:HandleUserSubmit:Ignoring empty user input...`); return; } chat.show(divChat); @@ -199,7 +198,7 @@ class MultiChatUI { inputUser.value = "working..."; inputUser.disabled = true; - console.debug(`DBUG:MCUI:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); + console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); let resp = await fetch(theUrl, { method: "POST", headers: { @@ -211,7 +210,7 @@ class MultiChatUI { inputUser.value = ""; inputUser.disabled = false; let respBody = await resp.json(); - console.debug("DBUG:MCUI:HandleUserSubmit:RespBody:", respBody); + console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${respBody}`); let assistantMsg; if (apiEP == ApiEP.Chat) { assistantMsg = respBody["choices"][0]["message"]["content"]; @@ -238,6 +237,7 @@ class MultiChatUI { let gMuitChat = new MultiChatUI(); +const gChatId = "Default"; function startme() { @@ -251,14 +251,15 @@ function startme() { if (divChat == null) { throw Error("ERRR:StartMe:Chat element missing"); } + console.log("INFO:StartMe:Starting..."); - gMuitChat.new_chat(); + gMuitChat.new_chat(gChatId); btnSubmit?.addEventListener("click", (ev)=>{ if (inputUser.disabled) { return; } - gMuitChat.handle_user_submit(inputSystem, inputUser, divChat, selectApiEP.value); + gMuitChat.handle_user_submit(gChatId, inputSystem, inputUser, divChat, selectApiEP.value); }); inputUser?.addEventListener("keyup", (ev)=> { From 1cd10ae9c4b400ae0a98fb0a5ff9afcc2b3b8860 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 09:43:02 +0530 Subject: [PATCH 50/64] SimpleChat: Move ui elements into MultiChatUI, Update el IDs Move ui elements into MultiChatUI, so that current handleUserSubmit doesnt need to take the element arguments. Also in future, when user is allowed to switch between different chat sessions, the UI can be updated as needed by using the elements in UI already known to MultiChatUI instance. Rename the element ids' so that they follow a common convention, as well as one can identify what the element represents in a more consistant manner. --- examples/server/public_simplechat/index.html | 10 +- .../server/public_simplechat/simplechat.css | 2 +- .../server/public_simplechat/simplechat.js | 104 ++++++++++-------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/examples/server/public_simplechat/index.html b/examples/server/public_simplechat/index.html index b7684193895e3..463c7953194b8 100644 --- a/examples/server/public_simplechat/index.html +++ b/examples/server/public_simplechat/index.html @@ -26,12 +26,12 @@
- - + +

-
+

Enter the system prompt above, before entering/submitting any user query.

Enter your text to the ai assistant below.

Use shift+enter for inserting enter.

@@ -40,8 +40,8 @@
- - + +
diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index 4797dd9b82713..944693e9d66c5 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -25,7 +25,7 @@ float: right; } -#chat { +#chat-div { overflow: scroll; flex-grow: 1; flex-shrink: 1; diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 4cd2fcecc0bc0..1ffc7a9536d1c 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -157,6 +157,53 @@ class MultiChatUI { constructor() { /** @type {Object} */ this.simpleChats = {}; + + // the ui elements + this.elInSystem = /** @type{HTMLInputElement} */(document.getElementById("system-in")); + this.elDivChat = /** @type{HTMLDivElement} */(document.getElementById("chat-div")); + this.elBtnUser = /** @type{HTMLButtonElement} */(document.getElementById("user-btn")); + this.elInUser = /** @type{HTMLInputElement} */(document.getElementById("user-in")); + this.elSelectApiEP = /** @type{HTMLSelectElement} */(document.getElementById("api-ep")); + + this.validate_element(this.elInSystem, "system-in"); + this.validate_element(this.elDivChat, "chat-div"); + this.validate_element(this.elInUser, "user-in"); + this.validate_element(this.elSelectApiEP, "api-ep"); + } + + /** + * Check if the element got + * @param {HTMLElement | null} el + * @param {string} msgTag + */ + validate_element(el, msgTag) { + if (el == null) { + throw Error(`ERRR:MCUI:${msgTag} element missing in html...`); + } else { + console.debug(`INFO:MCUI:${msgTag}:Id:${el.id}:Name:${el["name"]}`); + } + } + + /** + * Setup the needed callbacks wrt UI + * @param {string} chatId + */ + setup_ui(chatId) { + this.elBtnUser.addEventListener("click", (ev)=>{ + if (this.elInUser.disabled) { + return; + } + this.handle_user_submit(chatId, this.elSelectApiEP.value); + }); + + this.elInUser.addEventListener("keyup", (ev)=> { + // allow user to insert enter into their message using shift+enter. + // while just pressing enter key will lead to submitting. + if ((ev.key === "Enter") && (!ev.shiftKey)) { + this.elBtnUser.click(); + ev.preventDefault(); + } + }); } /** @@ -170,23 +217,20 @@ class MultiChatUI { /** * Handle user query submit request, wrt specified chat session. * @param {string} chatId - * @param {HTMLInputElement} inputSystem - * @param {HTMLInputElement} inputUser - * @param {HTMLDivElement} divChat * @param {string} apiEP */ - async handle_user_submit(chatId, inputSystem, inputUser, divChat, apiEP) { + async handle_user_submit(chatId, apiEP) { let chat = this.simpleChats[chatId]; - chat.add_system_anytime(inputSystem.value, chatId); + chat.add_system_anytime(this.elInSystem.value, chatId); - let content = inputUser.value; + let content = this.elInUser.value; if (!chat.add(Roles.User, content)) { console.debug(`WARN:MCUI:${chatId}:HandleUserSubmit:Ignoring empty user input...`); return; } - chat.show(divChat); + chat.show(this.elDivChat); let theBody; let theUrl = gChatURL[apiEP] @@ -196,8 +240,8 @@ class MultiChatUI { theBody = chat.request_prompt_jsonstr(); } - inputUser.value = "working..."; - inputUser.disabled = true; + this.elInUser.value = "working..."; + this.elInUser.disabled = true; console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); let resp = await fetch(theUrl, { method: "POST", @@ -207,8 +251,8 @@ class MultiChatUI { body: theBody, }); - inputUser.value = ""; - inputUser.disabled = false; + this.elInUser.value = ""; + this.elInUser.disabled = false; let respBody = await resp.json(); console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${respBody}`); let assistantMsg; @@ -222,7 +266,7 @@ class MultiChatUI { } } chat.add(Roles.Assistant, assistantMsg); - chat.show(divChat); + chat.show(this.elDivChat); // Purposefully clear at end rather than begin of this function // so that one can switch from chat to completion mode and sequece // in a completion mode with multiple user-assistant chat data @@ -230,48 +274,20 @@ class MultiChatUI { if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { chat.xchat.length = 0; } - inputUser.focus(); + this.elInUser.focus(); } } -let gMuitChat = new MultiChatUI(); +let gMuitChat; const gChatId = "Default"; - function startme() { - - let inputSystem = /** @type{HTMLInputElement} */(document.getElementById("system")); - let divChat = /** @type{HTMLDivElement} */(document.getElementById("chat")); - let btnSubmit = document.getElementById("submit"); - let inputUser = /** @type{HTMLInputElement} */(document.getElementById("user")); - let selectApiEP = /** @type{HTMLInputElement} */(document.getElementById("api-ep")); - - if (divChat == null) { - throw Error("ERRR:StartMe:Chat element missing"); - } console.log("INFO:StartMe:Starting..."); - + gMuitChat = new MultiChatUI(); gMuitChat.new_chat(gChatId); - - btnSubmit?.addEventListener("click", (ev)=>{ - if (inputUser.disabled) { - return; - } - gMuitChat.handle_user_submit(gChatId, inputSystem, inputUser, divChat, selectApiEP.value); - }); - - inputUser?.addEventListener("keyup", (ev)=> { - // allow user to insert enter into their message using shift+enter. - // while just pressing enter key will lead to submitting. - if ((ev.key === "Enter") && (!ev.shiftKey)) { - btnSubmit?.click(); - ev.preventDefault(); - } - }); - + gMuitChat.setup_ui(gChatId); } - document.addEventListener("DOMContentLoaded", startme); From 1b82f2281f41dc0684cc67db30ec5e1104b488a1 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 15:05:17 +0530 Subject: [PATCH 51/64] SimpleChat:MCUI:Show available chat sessions, try switch btw them Previous commits brought in / consolidated existing logic into MultiChatUI class. Now start adding logic towards multichat support * show buttons indicating available chat sessions * on sessin button click, try switch to that session --- examples/server/public_simplechat/index.html | 3 ++ .../server/public_simplechat/simplechat.js | 47 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/examples/server/public_simplechat/index.html b/examples/server/public_simplechat/index.html index 463c7953194b8..139db7e3f8478 100644 --- a/examples/server/public_simplechat/index.html +++ b/examples/server/public_simplechat/index.html @@ -25,6 +25,9 @@
+
+ +
diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 1ffc7a9536d1c..f25c672f8ce5f 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -164,6 +164,7 @@ class MultiChatUI { this.elBtnUser = /** @type{HTMLButtonElement} */(document.getElementById("user-btn")); this.elInUser = /** @type{HTMLInputElement} */(document.getElementById("user-in")); this.elSelectApiEP = /** @type{HTMLSelectElement} */(document.getElementById("api-ep")); + this.elDivSessions = /** @type{HTMLDivElement} */(document.getElementById("sessions-div")); this.validate_element(this.elInSystem, "system-in"); this.validate_element(this.elDivChat, "chat-div"); @@ -254,7 +255,7 @@ class MultiChatUI { this.elInUser.value = ""; this.elInUser.disabled = false; let respBody = await resp.json(); - console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${respBody}`); + console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${JSON.stringify(respBody)}`); let assistantMsg; if (apiEP == ApiEP.Chat) { assistantMsg = respBody["choices"][0]["message"]["content"]; @@ -277,6 +278,49 @@ class MultiChatUI { this.elInUser.focus(); } + /** + * Show buttons for available chat sessions, in the passed elDiv. + * If elDiv is undefined/null, then use this.elDivSessions. + * @param {HTMLDivElement | undefined} elDiv + */ + show_sessions(elDiv=undefined) { + if (!elDiv) { + elDiv = this.elDivSessions; + } + elDiv.replaceChildren(); + let chatIds = Object.keys(this.simpleChats); + for(let cid of chatIds) { + let btn = document.createElement("button"); + btn.id = cid; + btn.name = cid; + btn.innerText = cid; + btn.addEventListener("click", (ev)=>{ + let target = /** @type{HTMLButtonElement} */(ev.target); + console.debug(`DBUG:MCUI:SessionClick:${target.id}`); + if (this.elInUser.disabled) { + console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session awaiting response, skipping switch...`); + return; + } + this.handle_session_switch(target.id); + }); + elDiv.appendChild(btn); + } + } + + /** + * @param {string} chatId + */ + async handle_session_switch(chatId) { + let chat = this.simpleChats[chatId]; + if (chat == undefined) { + console.error(`ERRR:MCUI:Session:${chatId} missing...`); + return; + } + this.elInUser.value = ""; + chat.show(this.elDivChat); + this.elInUser.focus(); + } + } @@ -288,6 +332,7 @@ function startme() { gMuitChat = new MultiChatUI(); gMuitChat.new_chat(gChatId); gMuitChat.setup_ui(gChatId); + gMuitChat.show_sessions(); } document.addEventListener("DOMContentLoaded", startme); From 928cc364275e0744c94335c8c1541a5323323c7f Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 16:01:11 +0530 Subject: [PATCH 52/64] SimpleChat:MCUI: Store and use current chat session id Also allow to switch chat session optionally, wrt some of the related helpers. setup for two chat sessions by default. --- .../server/public_simplechat/simplechat.js | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index f25c672f8ce5f..998d0a2b2c73c 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -157,6 +157,8 @@ class MultiChatUI { constructor() { /** @type {Object} */ this.simpleChats = {}; + /** @type {string} */ + this.curChatId = ""; // the ui elements this.elInSystem = /** @type{HTMLInputElement} */(document.getElementById("system-in")); @@ -186,15 +188,22 @@ class MultiChatUI { } /** - * Setup the needed callbacks wrt UI - * @param {string} chatId + * Setup the needed callbacks wrt UI, curChatId to defaultChatId and + * optionally switch to specified defaultChatId. + * @param {string} defaultChatId + * @param {boolean} [bSwitchSession=false] */ - setup_ui(chatId) { + setup_ui(defaultChatId, bSwitchSession=false) { + this.curChatId = defaultChatId; + if (bSwitchSession) { + this.handle_session_switch(this.curChatId); + } + this.elBtnUser.addEventListener("click", (ev)=>{ if (this.elInUser.disabled) { return; } - this.handle_user_submit(chatId, this.elSelectApiEP.value); + this.handle_user_submit(this.curChatId, this.elSelectApiEP.value); }); this.elInUser.addEventListener("keyup", (ev)=> { @@ -208,11 +217,15 @@ class MultiChatUI { } /** - * Start a new chat session + * Setup a new chat session and optionally switch to it. * @param {string} chatId + * @param {boolean} [bSwitchSession=false] */ - new_chat(chatId) { + new_chat_session(chatId, bSwitchSession=false) { this.simpleChats[chatId] = new SimpleChat(); + if (bSwitchSession) { + this.handle_session_switch(chatId); + } } /** @@ -298,7 +311,7 @@ class MultiChatUI { let target = /** @type{HTMLButtonElement} */(ev.target); console.debug(`DBUG:MCUI:SessionClick:${target.id}`); if (this.elInUser.disabled) { - console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session awaiting response, skipping switch...`); + console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); return; } this.handle_session_switch(target.id); @@ -308,6 +321,7 @@ class MultiChatUI { } /** + * Switch ui to the specified chatId and set curChatId to same. * @param {string} chatId */ async handle_session_switch(chatId) { @@ -319,19 +333,22 @@ class MultiChatUI { this.elInUser.value = ""; chat.show(this.elDivChat); this.elInUser.focus(); + this.curChatId = chatId; } } let gMuitChat; -const gChatId = "Default"; +const gChatIds = [ "Default", "Other" ]; function startme() { console.log("INFO:StartMe:Starting..."); gMuitChat = new MultiChatUI(); - gMuitChat.new_chat(gChatId); - gMuitChat.setup_ui(gChatId); + for (let cid of gChatIds) { + gMuitChat.new_chat_session(cid); + } + gMuitChat.setup_ui(gChatIds[0]); gMuitChat.show_sessions(); } From d57274b2a3c34de6b00abe142b0a0a65af935550 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 16:48:32 +0530 Subject: [PATCH 53/64] SimpleChat:MCUI: Delay enabling user-input to avoid race Re-enable user-input, only after response to a user query has been updated to the chat-div. This ensures that if user tries to switch chat session, it wont be allowed till chat-request-response flow is done. --- examples/server/public_simplechat/simplechat.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 998d0a2b2c73c..57876cf8b42ed 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -265,8 +265,6 @@ class MultiChatUI { body: theBody, }); - this.elInUser.value = ""; - this.elInUser.disabled = false; let respBody = await resp.json(); console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${JSON.stringify(respBody)}`); let assistantMsg; @@ -288,6 +286,8 @@ class MultiChatUI { if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { chat.xchat.length = 0; } + this.elInUser.value = ""; + this.elInUser.disabled = false; this.elInUser.focus(); } From 7297dda3765082d9f19f6a34906a5bc8ae776ee7 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 17:24:06 +0530 Subject: [PATCH 54/64] SimpleChat: Take care of system prompt Helper to get the latest system prompt and inturn use same to set the system prompt ui, when switching. Ensure that system prompt is set if and when enter key is pressed. --- .../server/public_simplechat/simplechat.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 57876cf8b42ed..ce7d772758b98 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -141,6 +141,17 @@ class SimpleChat { return false; } + /** + * Retrieve the latest system prompt. + */ + get_system() { + let sysPrompt = this.xchat[this.iLastSys].content; + if (!sysPrompt) { + sysPrompt = ""; + } + return sysPrompt; + } + } @@ -194,6 +205,7 @@ class MultiChatUI { * @param {boolean} [bSwitchSession=false] */ setup_ui(defaultChatId, bSwitchSession=false) { + this.curChatId = defaultChatId; if (bSwitchSession) { this.handle_session_switch(this.curChatId); @@ -214,6 +226,17 @@ class MultiChatUI { ev.preventDefault(); } }); + + this.elInSystem.addEventListener("keyup", (ev)=> { + // allow user to insert enter into the system prompt using shift+enter. + // while just pressing enter key will lead to setting the system prompt. + if ((ev.key === "Enter") && (!ev.shiftKey)) { + let chat = this.simpleChats[this.curChatId]; + chat.add_system_anytime(this.elInSystem.value, this.curChatId); + ev.preventDefault(); + } + }); + } /** @@ -330,6 +353,7 @@ class MultiChatUI { console.error(`ERRR:MCUI:Session:${chatId} missing...`); return; } + this.elInSystem.value = chat.get_system(); this.elInUser.value = ""; chat.show(this.elDivChat); this.elInUser.focus(); From 3458d2f8c3baedfc241d425a9e0d2d8fc0290bb3 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 17:39:49 +0530 Subject: [PATCH 55/64] SimpleChat:GetSystemLatest, fix a oversight. --- examples/server/public_simplechat/simplechat.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index ce7d772758b98..2e3da03ca7cdb 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -144,11 +144,11 @@ class SimpleChat { /** * Retrieve the latest system prompt. */ - get_system() { - let sysPrompt = this.xchat[this.iLastSys].content; - if (!sysPrompt) { - sysPrompt = ""; + get_system_latest() { + if (this.iLastSys == -1) { + return ""; } + let sysPrompt = this.xchat[this.iLastSys].content; return sysPrompt; } @@ -353,7 +353,7 @@ class MultiChatUI { console.error(`ERRR:MCUI:Session:${chatId} missing...`); return; } - this.elInSystem.value = chat.get_system(); + this.elInSystem.value = chat.get_system_latest(); this.elInUser.value = ""; chat.show(this.elDivChat); this.elInUser.focus(); From b9f9c0ec6e4398bce09cb5e6850fab7073e2f460 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 17:48:18 +0530 Subject: [PATCH 56/64] SimpleChat:MCUI: Allow selected chat-session btn to be highlighted Also have a general helper for setting class of children. --- .../server/public_simplechat/simplechat.css | 4 ++++ .../server/public_simplechat/simplechat.js | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.css b/examples/server/public_simplechat/simplechat.css index 944693e9d66c5..d45f50a957e4c 100644 --- a/examples/server/public_simplechat/simplechat.css +++ b/examples/server/public_simplechat/simplechat.css @@ -11,6 +11,10 @@ background-color: lightgray; } +.session-selected { + background-color: lightblue; +} + .role-system { background-color: lightblue; } diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 2e3da03ca7cdb..e2126c2dec6f0 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -163,6 +163,23 @@ let gChatURL = { const gbCompletionFreshChatAlways = true; +/** + * Set the class of the children, based on whether it is the idSelected or not. + * @param {HTMLDivElement} elBase + * @param {string} idSelected + * @param {string} classSelected + * @param {string} classUnSelected + */ +function el_children_config_class(elBase, idSelected, classSelected, classUnSelected="") { + for(let child of elBase.children) { + if (child.id == idSelected) { + child.className = classSelected; + } else { + child.className = classUnSelected; + } + } +} + class MultiChatUI { constructor() { @@ -317,6 +334,7 @@ class MultiChatUI { /** * Show buttons for available chat sessions, in the passed elDiv. * If elDiv is undefined/null, then use this.elDivSessions. + * Take care of highlighting the selected chat-session's btn. * @param {HTMLDivElement | undefined} elDiv */ show_sessions(elDiv=undefined) { @@ -330,6 +348,9 @@ class MultiChatUI { btn.id = cid; btn.name = cid; btn.innerText = cid; + if (cid == this.curChatId) { + btn.className = "session-selected"; + } btn.addEventListener("click", (ev)=>{ let target = /** @type{HTMLButtonElement} */(ev.target); console.debug(`DBUG:MCUI:SessionClick:${target.id}`); @@ -338,6 +359,7 @@ class MultiChatUI { return; } this.handle_session_switch(target.id); + el_children_config_class(elDiv, target.id, "session-selected", ""); }); elDiv.appendChild(btn); } From 68ef7401edcedf4a806594911770fce38ce08d83 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 18:33:27 +0530 Subject: [PATCH 57/64] SimpleChat:Cleanup corners Show system prompt in chat space, when it is set by pressing enter, as a feedback to user. Alert user, if they try to switch chat session in the middle of waiting for a response from the ai model. --- examples/server/public_simplechat/simplechat.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index e2126c2dec6f0..1c0e1bda19053 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -250,6 +250,7 @@ class MultiChatUI { if ((ev.key === "Enter") && (!ev.shiftKey)) { let chat = this.simpleChats[this.curChatId]; chat.add_system_anytime(this.elInSystem.value, this.curChatId); + chat.show(this.elDivChat); ev.preventDefault(); } }); @@ -356,6 +357,7 @@ class MultiChatUI { console.debug(`DBUG:MCUI:SessionClick:${target.id}`); if (this.elInUser.disabled) { console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); + alert("ERRR:MCUI\nWait for response to pending query, before switching"); return; } this.handle_session_switch(target.id); From 2a407192fc3901117ad0fe7afb4f865a0de14dc4 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 18:51:14 +0530 Subject: [PATCH 58/64] SimpleChat:MCUI: Ensure req-resp failure doesnt lock up things --- .../server/public_simplechat/simplechat.js | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 1c0e1bda19053..6aa57d482bbc5 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -215,6 +215,18 @@ class MultiChatUI { } } + /** + * Reset user input ui. + * * clear user input + * * enable user input + * * set focus to user input + */ + ui_reset_userinput() { + this.elInUser.value = ""; + this.elInUser.disabled = false; + this.elInUser.focus(); + } + /** * Setup the needed callbacks wrt UI, curChatId to defaultChatId and * optionally switch to specified defaultChatId. @@ -232,7 +244,12 @@ class MultiChatUI { if (this.elInUser.disabled) { return; } - this.handle_user_submit(this.curChatId, this.elSelectApiEP.value); + this.handle_user_submit(this.curChatId, this.elSelectApiEP.value).catch((/** @type{Error} */reason)=>{ + let msg = `ERRR:MCUI:HandleUserSubmit\n${reason.name}:${reason.message}`; + console.debug(msg.replace("\n", ":")); + alert(msg); + this.ui_reset_userinput(); + }); }); this.elInUser.addEventListener("keyup", (ev)=> { @@ -327,9 +344,7 @@ class MultiChatUI { if ((apiEP == ApiEP.Completion) && (gbCompletionFreshChatAlways)) { chat.xchat.length = 0; } - this.elInUser.value = ""; - this.elInUser.disabled = false; - this.elInUser.focus(); + this.ui_reset_userinput(); } /** From 14083d157f42fb6744fed460e0e91fb0dcd2a8bd Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 19:56:21 +0530 Subject: [PATCH 59/64] SimpleChat:MCUI: Support for new chat sessions Also a general create button helper. --- .../server/public_simplechat/simplechat.js | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 6aa57d482bbc5..5a3fe09439889 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -180,6 +180,29 @@ function el_children_config_class(elBase, idSelected, classSelected, classUnSele } } +/** + * Create button and set it up. + * @param {string} id + * @param {(this: HTMLButtonElement, ev: MouseEvent) => any} callback + * @param {string | undefined} name + * @param {string | undefined} innerText + */ +function el_create_button(id, callback, name=undefined, innerText=undefined) { + if (!name) { + name = id; + } + if (!innerText) { + innerText = id; + } + let btn = document.createElement("button"); + btn.id = id; + btn.name = name; + btn.innerText = innerText; + btn.addEventListener("click", callback); + return btn; +} + + class MultiChatUI { constructor() { @@ -360,14 +383,7 @@ class MultiChatUI { elDiv.replaceChildren(); let chatIds = Object.keys(this.simpleChats); for(let cid of chatIds) { - let btn = document.createElement("button"); - btn.id = cid; - btn.name = cid; - btn.innerText = cid; - if (cid == this.curChatId) { - btn.className = "session-selected"; - } - btn.addEventListener("click", (ev)=>{ + let btn = el_create_button(cid, (ev)=>{ let target = /** @type{HTMLButtonElement} */(ev.target); console.debug(`DBUG:MCUI:SessionClick:${target.id}`); if (this.elInUser.disabled) { @@ -378,8 +394,17 @@ class MultiChatUI { this.handle_session_switch(target.id); el_children_config_class(elDiv, target.id, "session-selected", ""); }); + if (cid == this.curChatId) { + btn.className = "session-selected"; + } elDiv.appendChild(btn); } + let btnNew = el_create_button("NeW cHaT", (ev)=> { + let chatId = `Chat${chatIds.length}`; + let chatName = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); + this.new_chat_session(chatId, true); + }); + elDiv.appendChild(btnNew); } /** From 6c712775130c5bcc300e8342bbbcee1efcd73554 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 20:19:25 +0530 Subject: [PATCH 60/64] SimpleChat:MCUI: CreateSessionBtn helper, use wrt NewChat Also fix a oversight wrt using stale data wrt the list of chat sessions. --- .../server/public_simplechat/simplechat.js | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 5a3fe09439889..6eec2658671e3 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -383,30 +383,40 @@ class MultiChatUI { elDiv.replaceChildren(); let chatIds = Object.keys(this.simpleChats); for(let cid of chatIds) { - let btn = el_create_button(cid, (ev)=>{ - let target = /** @type{HTMLButtonElement} */(ev.target); - console.debug(`DBUG:MCUI:SessionClick:${target.id}`); - if (this.elInUser.disabled) { - console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); - alert("ERRR:MCUI\nWait for response to pending query, before switching"); - return; - } - this.handle_session_switch(target.id); - el_children_config_class(elDiv, target.id, "session-selected", ""); - }); + let btn = this.create_session_btn(elDiv, cid); if (cid == this.curChatId) { btn.className = "session-selected"; } - elDiv.appendChild(btn); } let btnNew = el_create_button("NeW cHaT", (ev)=> { - let chatId = `Chat${chatIds.length}`; - let chatName = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); - this.new_chat_session(chatId, true); + let chatId = `Chat${Object.keys(this.simpleChats).length}`; + let chatIdGot = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); + if (!chatIdGot) { + chatIdGot = chatId; + } + this.new_chat_session(chatIdGot, true); + this.create_session_btn(elDiv, chatIdGot); + el_children_config_class(elDiv, chatIdGot, "session-selected", ""); }); elDiv.appendChild(btnNew); } + create_session_btn(elDiv, cid) { + let btn = el_create_button(cid, (ev)=>{ + let target = /** @type{HTMLButtonElement} */(ev.target); + console.debug(`DBUG:MCUI:SessionClick:${target.id}`); + if (this.elInUser.disabled) { + console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); + alert("ERRR:MCUI\nWait for response to pending query, before switching"); + return; + } + this.handle_session_switch(target.id); + el_children_config_class(elDiv, target.id, "session-selected", ""); + }); + elDiv.appendChild(btn); + return btn; + } + /** * Switch ui to the specified chatId and set curChatId to same. * @param {string} chatId From d3405ea0724cf691823433a60798a8a5585cc20e Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 21:07:34 +0530 Subject: [PATCH 61/64] SimpleChat:MCUI: NewChat btn first before existing chat sessions --- .../server/public_simplechat/simplechat.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 6eec2658671e3..97edd730b2a61 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -254,7 +254,7 @@ class MultiChatUI { * Setup the needed callbacks wrt UI, curChatId to defaultChatId and * optionally switch to specified defaultChatId. * @param {string} defaultChatId - * @param {boolean} [bSwitchSession=false] + * @param {boolean} bSwitchSession */ setup_ui(defaultChatId, bSwitchSession=false) { @@ -300,7 +300,7 @@ class MultiChatUI { /** * Setup a new chat session and optionally switch to it. * @param {string} chatId - * @param {boolean} [bSwitchSession=false] + * @param {boolean} bSwitchSession */ new_chat_session(chatId, bSwitchSession=false) { this.simpleChats[chatId] = new SimpleChat(); @@ -371,7 +371,7 @@ class MultiChatUI { } /** - * Show buttons for available chat sessions, in the passed elDiv. + * Show buttons for NewChat and available chat sessions, in the passed elDiv. * If elDiv is undefined/null, then use this.elDivSessions. * Take care of highlighting the selected chat-session's btn. * @param {HTMLDivElement | undefined} elDiv @@ -381,13 +381,7 @@ class MultiChatUI { elDiv = this.elDivSessions; } elDiv.replaceChildren(); - let chatIds = Object.keys(this.simpleChats); - for(let cid of chatIds) { - let btn = this.create_session_btn(elDiv, cid); - if (cid == this.curChatId) { - btn.className = "session-selected"; - } - } + // Btn for creating new chat session let btnNew = el_create_button("NeW cHaT", (ev)=> { let chatId = `Chat${Object.keys(this.simpleChats).length}`; let chatIdGot = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); @@ -399,6 +393,14 @@ class MultiChatUI { el_children_config_class(elDiv, chatIdGot, "session-selected", ""); }); elDiv.appendChild(btnNew); + // Btns for existing chat sessions + let chatIds = Object.keys(this.simpleChats); + for(let cid of chatIds) { + let btn = this.create_session_btn(elDiv, cid); + if (cid == this.curChatId) { + btn.className = "session-selected"; + } + } } create_session_btn(elDiv, cid) { From c2e8d62707a686fefff44b71b823c0239b600cd2 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 21:55:05 +0530 Subject: [PATCH 62/64] SimpleChat:MCUI:CornerCases:Skip new chat, show only if current Skip NewChat if user cancels or if one waiting for response from the ai model. Dont show a chat with newly got ai model response, if current chat session has changed, some how. Chat session shouldnt be allowed to change, if there is a pending response, but still as a additional sanity check. --- examples/server/public_simplechat/simplechat.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 97edd730b2a61..b9dd2a281ae1d 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -359,7 +359,11 @@ class MultiChatUI { } } chat.add(Roles.Assistant, assistantMsg); - chat.show(this.elDivChat); + if (chatId == this.curChatId) { + chat.show(this.elDivChat); + } else { + console.debug(`DBUG:MCUI:HandleUserSubmit:ChatId has changed:[${chatId}] [${this.curChatId}]`); + } // Purposefully clear at end rather than begin of this function // so that one can switch from chat to completion mode and sequece // in a completion mode with multiple user-assistant chat data @@ -382,11 +386,17 @@ class MultiChatUI { } elDiv.replaceChildren(); // Btn for creating new chat session - let btnNew = el_create_button("NeW cHaT", (ev)=> { + let btnNew = el_create_button("New CHAT", (ev)=> { + if (this.elInUser.disabled) { + console.error(`ERRR:MCUI:NewChatClick:Current session [${this.curChatId}] awaiting response, ignoring request...`); + alert("ERRR:MCUI\nWait for response to pending query, before starting new chat session"); + return; + } let chatId = `Chat${Object.keys(this.simpleChats).length}`; let chatIdGot = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); if (!chatIdGot) { - chatIdGot = chatId; + console.error("ERRR:MCUI:NewChat:Skipping based on user request..."); + return; } this.new_chat_session(chatIdGot, true); this.create_session_btn(elDiv, chatIdGot); From fb848b296b02341996bc0546fef218e6f7014118 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Tue, 21 May 2024 23:02:47 +0530 Subject: [PATCH 63/64] SimpleChat: Update readme, title, show usage if no chat to show --- examples/server/public_simplechat/index.html | 4 ++-- examples/server/public_simplechat/readme.md | 20 +++++++++---------- .../server/public_simplechat/simplechat.js | 11 ++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/examples/server/public_simplechat/index.html b/examples/server/public_simplechat/index.html index 139db7e3f8478..1eb390b85a69c 100644 --- a/examples/server/public_simplechat/index.html +++ b/examples/server/public_simplechat/index.html @@ -1,11 +1,11 @@ - Simple LlamaCPP Chat + SimpleChat (LlamaCPP, ...) - + diff --git a/examples/server/public_simplechat/readme.md b/examples/server/public_simplechat/readme.md index 0f6a1cee069e0..5ac8258f21aca 100644 --- a/examples/server/public_simplechat/readme.md +++ b/examples/server/public_simplechat/readme.md @@ -7,11 +7,9 @@ by Humans for All. ## overview This simple web frontend, allows triggering/testing the server's /completions or /chat/completions endpoints -in a simple way with minimal code from a common code base. And also allows trying to maintain a basic back -and forth chatting to an extent. - -User can set a system prompt, as well as try and chat with the model over a series of back and forth chat -messages. +in a simple way with minimal code from a common code base. Inturn additionally it tries to allow single or +multiple independent back and forth chatting to an extent, with the ai llm model at a basic level, with their +own system prompts. The UI follows a responsive web design so that the layout can adapt to available display space in a usable enough manner, in general. @@ -50,10 +48,10 @@ Open this simple web front end from your local browser Once inside * Select between chat and completion mode. By default it is set to chat mode. * If you want to provide a system prompt, then ideally enter it first, before entering any user query. - * if handle_systemprompt_begin is used + * if chat.add_system_begin is used * you cant change the system prompt, after it is has been submitted once along with user query. * you cant set a system prompt, after you have submitted any user query - * if handle_systemprompt_anytime is used + * if chat.add_system_anytime is used * one can change the system prompt any time during chat, by changing the contents of system prompt. * inturn the updated/changed system prompt will be inserted into the chat session. * this allows for the subsequent user chatting to be driven by the new system prompt set above. @@ -63,6 +61,8 @@ Once inside * the user is not allowed to enter any fresh query during this time. * the user input box will be disabled and a working message will be shown in it. * just refresh the page, to reset wrt the chat history and or system prompt and start afresh. +* Using NewChat one can start independent chat sessions. + * two independent chat sessions are setup by default. ## Devel note @@ -72,10 +72,10 @@ may not be visible. Also remember that just refreshing/reloading page in browser matter clearing site data, dont directly override site caching in all cases. Worst case you may have to change port. Or in dev tools of browser, you may be able to disable caching fully. -Concept of multiple chat sessions with same or different system prompts, as well as saving and -restoring of those across browser usage sessions, can be woven around the SimpleChat class and +Concept of multiple chat sessions with different servers, as well as saving and restoring of +those across browser usage sessions, can be woven around the SimpleChat/MultiChatUI class and its instances relatively easily, however given the current goal of keeping this simple, it has not been added, for now. -By switching between handle_systemprompt_begin/anytime, one can control whether one can change +By switching between chat.add_system_begin/anytime, one can control whether one can change the system prompt, anytime during the conversation or only at the beginning. diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index b9dd2a281ae1d..13ca6c5238631 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -13,6 +13,13 @@ class ApiEP { static Completion = "completion"; } +let gUsageMsg = ` +

Enter the system prompt above, before entering/submitting any user query.

+

Enter your text to the ai assistant below.

+

Use shift+enter for inserting enter.

+

Refresh the page to start over fresh.

+`; + class SimpleChat { constructor() { @@ -59,6 +66,10 @@ class SimpleChat { } if (last !== undefined) { last.scrollIntoView(false); + } else { + if (bClear) { + div.innerHTML = gUsageMsg; + } } } From 1d87c50201cb225effce6bb6522a79f390b091d7 Mon Sep 17 00:00:00 2001 From: HanishKVC Date: Wed, 22 May 2024 00:42:50 +0530 Subject: [PATCH 64/64] SimpleChat: Cleanup the log/dialog messages a bit --- .../server/public_simplechat/simplechat.js | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/examples/server/public_simplechat/simplechat.js b/examples/server/public_simplechat/simplechat.js index 13ca6c5238631..3fc4dbc2026fa 100644 --- a/examples/server/public_simplechat/simplechat.js +++ b/examples/server/public_simplechat/simplechat.js @@ -120,10 +120,10 @@ class SimpleChat { } else { if (sysPrompt.length > 0) { if (this.xchat[0].role !== Roles.System) { - console.error(`ERRR:SimpleChat:${msgTag}:You need to specify system prompt before any user query, ignoring...`); + console.error(`ERRR:SimpleChat:SC:${msgTag}:You need to specify system prompt before any user query, ignoring...`); } else { if (this.xchat[0].content !== sysPrompt) { - console.error(`ERRR:SimpleChat:${msgTag}:You cant change system prompt, mid way through, ignoring...`); + console.error(`ERRR:SimpleChat:SC:${msgTag}:You cant change system prompt, mid way through, ignoring...`); } } } @@ -234,6 +234,7 @@ class MultiChatUI { this.validate_element(this.elDivChat, "chat-div"); this.validate_element(this.elInUser, "user-in"); this.validate_element(this.elSelectApiEP, "api-ep"); + this.validate_element(this.elDivChat, "sessions-div"); } /** @@ -243,9 +244,9 @@ class MultiChatUI { */ validate_element(el, msgTag) { if (el == null) { - throw Error(`ERRR:MCUI:${msgTag} element missing in html...`); + throw Error(`ERRR:SimpleChat:MCUI:${msgTag} element missing in html...`); } else { - console.debug(`INFO:MCUI:${msgTag}:Id:${el.id}:Name:${el["name"]}`); + console.debug(`INFO:SimpleChat:MCUI:${msgTag} Id[${el.id}] Name[${el["name"]}]`); } } @@ -279,7 +280,7 @@ class MultiChatUI { return; } this.handle_user_submit(this.curChatId, this.elSelectApiEP.value).catch((/** @type{Error} */reason)=>{ - let msg = `ERRR:MCUI:HandleUserSubmit\n${reason.name}:${reason.message}`; + let msg = `ERRR:SimpleChat\nMCUI:HandleUserSubmit:${this.curChatId}\n${reason.name}:${reason.message}`; console.debug(msg.replace("\n", ":")); alert(msg); this.ui_reset_userinput(); @@ -333,7 +334,7 @@ class MultiChatUI { let content = this.elInUser.value; if (!chat.add(Roles.User, content)) { - console.debug(`WARN:MCUI:${chatId}:HandleUserSubmit:Ignoring empty user input...`); + console.debug(`WARN:SimpleChat:MCUI:${chatId}:HandleUserSubmit:Ignoring empty user input...`); return; } chat.show(this.elDivChat); @@ -348,7 +349,7 @@ class MultiChatUI { this.elInUser.value = "working..."; this.elInUser.disabled = true; - console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); + console.debug(`DBUG:SimpleChat:MCUI:${chatId}:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); let resp = await fetch(theUrl, { method: "POST", headers: { @@ -358,7 +359,7 @@ class MultiChatUI { }); let respBody = await resp.json(); - console.debug(`DBUG:MCUI:${chatId}:HandleUserSubmit:RespBody:${JSON.stringify(respBody)}`); + console.debug(`DBUG:SimpleChat:MCUI:${chatId}:HandleUserSubmit:RespBody:${JSON.stringify(respBody)}`); let assistantMsg; if (apiEP == ApiEP.Chat) { assistantMsg = respBody["choices"][0]["message"]["content"]; @@ -373,7 +374,7 @@ class MultiChatUI { if (chatId == this.curChatId) { chat.show(this.elDivChat); } else { - console.debug(`DBUG:MCUI:HandleUserSubmit:ChatId has changed:[${chatId}] [${this.curChatId}]`); + console.debug(`DBUG:SimpleChat:MCUI:HandleUserSubmit:ChatId has changed:[${chatId}] [${this.curChatId}]`); } // Purposefully clear at end rather than begin of this function // so that one can switch from chat to completion mode and sequece @@ -399,14 +400,14 @@ class MultiChatUI { // Btn for creating new chat session let btnNew = el_create_button("New CHAT", (ev)=> { if (this.elInUser.disabled) { - console.error(`ERRR:MCUI:NewChatClick:Current session [${this.curChatId}] awaiting response, ignoring request...`); - alert("ERRR:MCUI\nWait for response to pending query, before starting new chat session"); + console.error(`ERRR:SimpleChat:MCUI:NewChat:Current session [${this.curChatId}] awaiting response, ignoring request...`); + alert("ERRR:SimpleChat\nMCUI:NewChat\nWait for response to pending query, before starting new chat session"); return; } let chatId = `Chat${Object.keys(this.simpleChats).length}`; - let chatIdGot = prompt("SimpleChat:MCUI:\nEnter id for new chat session", chatId); + let chatIdGot = prompt("INFO:SimpleChat\nMCUI:NewChat\nEnter id for new chat session", chatId); if (!chatIdGot) { - console.error("ERRR:MCUI:NewChat:Skipping based on user request..."); + console.error("ERRR:SimpleChat:MCUI:NewChat:Skipping based on user request..."); return; } this.new_chat_session(chatIdGot, true); @@ -427,10 +428,10 @@ class MultiChatUI { create_session_btn(elDiv, cid) { let btn = el_create_button(cid, (ev)=>{ let target = /** @type{HTMLButtonElement} */(ev.target); - console.debug(`DBUG:MCUI:SessionClick:${target.id}`); + console.debug(`DBUG:SimpleChat:MCUI:SessionClick:${target.id}`); if (this.elInUser.disabled) { - console.error(`ERRR:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); - alert("ERRR:MCUI\nWait for response to pending query, before switching"); + console.error(`ERRR:SimpleChat:MCUI:SessionClick:${target.id}:Current session [${this.curChatId}] awaiting response, ignoring switch...`); + alert("ERRR:SimpleChat\nMCUI:SessionClick\nWait for response to pending query, before switching"); return; } this.handle_session_switch(target.id); @@ -447,7 +448,7 @@ class MultiChatUI { async handle_session_switch(chatId) { let chat = this.simpleChats[chatId]; if (chat == undefined) { - console.error(`ERRR:MCUI:Session:${chatId} missing...`); + console.error(`ERRR:SimpleChat:MCUI:HandleSessionSwitch:${chatId} missing...`); return; } this.elInSystem.value = chat.get_system_latest(); @@ -455,6 +456,7 @@ class MultiChatUI { chat.show(this.elDivChat); this.elInUser.focus(); this.curChatId = chatId; + console.log(`INFO:SimpleChat:MCUI:HandleSessionSwitch:${chatId} entered...`); } } @@ -464,7 +466,7 @@ let gMuitChat; const gChatIds = [ "Default", "Other" ]; function startme() { - console.log("INFO:StartMe:Starting..."); + console.log("INFO:SimpleChat:StartMe:Starting..."); gMuitChat = new MultiChatUI(); for (let cid of gChatIds) { gMuitChat.new_chat_session(cid);