|
|
|
|
|
|
|
|
|
import * as du from "./datautils.mjs"; |
|
import * as ui from "./ui.mjs" |
|
|
|
class Roles { |
|
static System = "system"; |
|
static User = "user"; |
|
static Assistant = "assistant"; |
|
} |
|
|
|
class ApiEP { |
|
static Type = { |
|
Chat: "chat", |
|
Completion: "completion", |
|
} |
|
static UrlSuffix = { |
|
'chat': `/chat/completions`, |
|
'completion': `/completions`, |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
static Url(baseUrl, apiEP) { |
|
if (baseUrl.endsWith("/")) { |
|
baseUrl = baseUrl.substring(0, baseUrl.length-1); |
|
} |
|
return `${baseUrl}${this.UrlSuffix[apiEP]}`; |
|
} |
|
|
|
} |
|
|
|
|
|
let gUsageMsg = ` |
|
<p class="role-system">Usage</p> |
|
<ul class="ul1"> |
|
<li> System prompt above, to try control ai response characteristics.</li> |
|
<ul class="ul2"> |
|
<li> Completion mode - no system prompt normally.</li> |
|
</ul> |
|
<li> Use shift+enter for inserting enter/newline.</li> |
|
<li> Enter your query to ai assistant below.</li> |
|
<li> Default ContextWindow = [System, Last Query+Resp, Cur Query].</li> |
|
<ul class="ul2"> |
|
<li> ChatHistInCtxt, MaxTokens, ModelCtxt window to expand</li> |
|
</ul> |
|
</ul> |
|
`; |
|
|
|
|
|
|
|
|
|
|
|
|
|
class SimpleChat { |
|
|
|
|
|
|
|
|
|
constructor(chatId) { |
|
this.chatId = chatId; |
|
|
|
|
|
|
|
|
|
this.xchat = []; |
|
this.iLastSys = -1; |
|
this.latestResponse = ""; |
|
} |
|
|
|
clear() { |
|
this.xchat = []; |
|
this.iLastSys = -1; |
|
} |
|
|
|
ods_key() { |
|
return `SimpleChat-${this.chatId}` |
|
} |
|
|
|
save() { |
|
|
|
let ods = {iLastSys: this.iLastSys, xchat: this.xchat}; |
|
localStorage.setItem(this.ods_key(), JSON.stringify(ods)); |
|
} |
|
|
|
load() { |
|
let sods = localStorage.getItem(this.ods_key()); |
|
if (sods == null) { |
|
return; |
|
} |
|
|
|
let ods = JSON.parse(sods); |
|
this.iLastSys = ods.iLastSys; |
|
this.xchat = ods.xchat; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
recent_chat(iRecentUserMsgCnt) { |
|
if (iRecentUserMsgCnt < 0) { |
|
return this.xchat; |
|
} |
|
if (iRecentUserMsgCnt == 0) { |
|
console.warn("WARN:SimpleChat:SC:RecentChat:iRecentUsermsgCnt of 0 means no user message/query sent"); |
|
} |
|
|
|
let rchat = []; |
|
let sysMsg = this.get_system_latest(); |
|
if (sysMsg.length != 0) { |
|
rchat.push({role: Roles.System, content: sysMsg}); |
|
} |
|
let iUserCnt = 0; |
|
let iStart = this.xchat.length; |
|
for(let i=this.xchat.length-1; i > this.iLastSys; i--) { |
|
if (iUserCnt >= iRecentUserMsgCnt) { |
|
break; |
|
} |
|
let msg = this.xchat[i]; |
|
if (msg.role == Roles.User) { |
|
iStart = i; |
|
iUserCnt += 1; |
|
} |
|
} |
|
for(let i = iStart; i < this.xchat.length; i++) { |
|
let msg = this.xchat[i]; |
|
if (msg.role == Roles.System) { |
|
continue; |
|
} |
|
rchat.push({role: msg.role, content: msg.content}); |
|
} |
|
return rchat; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
append_response(content) { |
|
this.latestResponse += content; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
add(role, content) { |
|
if ((content == undefined) || (content == null) || (content == "")) { |
|
return false; |
|
} |
|
this.xchat.push( {role: role, content: content} ); |
|
if (role == Roles.System) { |
|
this.iLastSys = this.xchat.length - 1; |
|
} |
|
this.save(); |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
show(div, bClear=true) { |
|
if (bClear) { |
|
div.replaceChildren(); |
|
} |
|
let last = undefined; |
|
for(const x of this.recent_chat(gMe.iRecentUserMsgCnt)) { |
|
let entry = ui.el_create_append_p(`${x.role}: ${x.content}`, div); |
|
entry.className = `role-${x.role}`; |
|
last = entry; |
|
} |
|
if (last !== undefined) { |
|
last.scrollIntoView(false); |
|
} else { |
|
if (bClear) { |
|
div.innerHTML = gUsageMsg; |
|
gMe.setup_load(div, this); |
|
gMe.show_info(div); |
|
} |
|
} |
|
return last; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fetch_headers(apiEP) { |
|
let headers = new Headers(); |
|
for(let k in gMe.headers) { |
|
let v = gMe.headers[k]; |
|
if ((k == "Authorization") && (v.trim() == "")) { |
|
continue; |
|
} |
|
headers.append(k, v); |
|
} |
|
return headers; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
request_jsonstr_extend(obj) { |
|
for(let k in gMe.apiRequestOptions) { |
|
obj[k] = gMe.apiRequestOptions[k]; |
|
} |
|
if (gMe.bStream) { |
|
obj["stream"] = true; |
|
} |
|
return JSON.stringify(obj); |
|
} |
|
|
|
|
|
|
|
|
|
request_messages_jsonstr() { |
|
let req = { |
|
messages: this.recent_chat(gMe.iRecentUserMsgCnt), |
|
} |
|
return this.request_jsonstr_extend(req); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
request_prompt_jsonstr(bInsertStandardRolePrefix) { |
|
let prompt = ""; |
|
let iCnt = 0; |
|
for(const chat of this.recent_chat(gMe.iRecentUserMsgCnt)) { |
|
iCnt += 1; |
|
if (iCnt > 1) { |
|
prompt += "\n"; |
|
} |
|
if (bInsertStandardRolePrefix) { |
|
prompt += `${chat.role}: `; |
|
} |
|
prompt += `${chat.content}`; |
|
} |
|
let req = { |
|
prompt: prompt, |
|
} |
|
return this.request_jsonstr_extend(req); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
request_jsonstr(apiEP) { |
|
if (apiEP == ApiEP.Type.Chat) { |
|
return this.request_messages_jsonstr(); |
|
} else { |
|
return this.request_prompt_jsonstr(gMe.bCompletionInsertStandardRolePrefix); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
response_extract(respBody, apiEP) { |
|
let assistant = ""; |
|
if (apiEP == ApiEP.Type.Chat) { |
|
assistant = respBody["choices"][0]["message"]["content"]; |
|
} else { |
|
try { |
|
assistant = respBody["choices"][0]["text"]; |
|
} catch { |
|
assistant = respBody["content"]; |
|
} |
|
} |
|
return assistant; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
response_extract_stream(respBody, apiEP) { |
|
let assistant = ""; |
|
if (apiEP == ApiEP.Type.Chat) { |
|
if (respBody["choices"][0]["finish_reason"] !== "stop") { |
|
assistant = respBody["choices"][0]["delta"]["content"]; |
|
} |
|
} else { |
|
try { |
|
assistant = respBody["choices"][0]["text"]; |
|
} catch { |
|
assistant = respBody["content"]; |
|
} |
|
} |
|
return assistant; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
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:SC:${msgTag}:You need to specify system prompt before any user query, ignoring...`); |
|
} else { |
|
if (this.xchat[0].content !== sysPrompt) { |
|
console.error(`ERRR:SimpleChat:SC:${msgTag}:You cant change system prompt, mid way through, ignoring...`); |
|
} |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
add_system_anytime(sysPrompt, msgTag) { |
|
if (sysPrompt.length <= 0) { |
|
return false; |
|
} |
|
|
|
if (this.iLastSys < 0) { |
|
return this.add(Roles.System, sysPrompt); |
|
} |
|
|
|
let lastSys = this.xchat[this.iLastSys].content; |
|
if (lastSys !== sysPrompt) { |
|
return this.add(Roles.System, sysPrompt); |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
get_system_latest() { |
|
if (this.iLastSys == -1) { |
|
return ""; |
|
} |
|
let sysPrompt = this.xchat[this.iLastSys].content; |
|
return sysPrompt; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async handle_response_multipart(resp, apiEP, elDiv) { |
|
let elP = ui.el_create_append_p("", elDiv); |
|
if (!resp.body) { |
|
throw Error("ERRR:SimpleChat:SC:HandleResponseMultiPart:No body..."); |
|
} |
|
let tdUtf8 = new TextDecoder("utf-8"); |
|
let rr = resp.body.getReader(); |
|
this.latestResponse = ""; |
|
let xLines = new du.NewLines(); |
|
while(true) { |
|
let { value: cur, done: done } = await rr.read(); |
|
if (cur) { |
|
let curBody = tdUtf8.decode(cur, {stream: true}); |
|
console.debug("DBUG:SC:PART:Str:", curBody); |
|
xLines.add_append(curBody); |
|
} |
|
while(true) { |
|
let curLine = xLines.shift(!done); |
|
if (curLine == undefined) { |
|
break; |
|
} |
|
if (curLine.trim() == "") { |
|
continue; |
|
} |
|
if (curLine.startsWith("data:")) { |
|
curLine = curLine.substring(5); |
|
} |
|
let curJson = JSON.parse(curLine); |
|
console.debug("DBUG:SC:PART:Json:", curJson); |
|
this.append_response(this.response_extract_stream(curJson, apiEP)); |
|
} |
|
elP.innerText = this.latestResponse; |
|
elP.scrollIntoView(false); |
|
if (done) { |
|
break; |
|
} |
|
} |
|
console.debug("DBUG:SC:PART:Full:", this.latestResponse); |
|
return this.latestResponse; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
async handle_response_oneshot(resp, apiEP) { |
|
let respBody = await resp.json(); |
|
console.debug(`DBUG:SimpleChat:SC:${this.chatId}:HandleUserSubmit:RespBody:${JSON.stringify(respBody)}`); |
|
return this.response_extract(respBody, apiEP); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async handle_response(resp, apiEP, elDiv) { |
|
let theResp = { |
|
assistant: "", |
|
trimmed: "", |
|
} |
|
if (gMe.bStream) { |
|
try { |
|
theResp.assistant = await this.handle_response_multipart(resp, apiEP, elDiv); |
|
this.latestResponse = ""; |
|
} catch (error) { |
|
theResp.assistant = this.latestResponse; |
|
this.add(Roles.Assistant, theResp.assistant); |
|
this.latestResponse = ""; |
|
throw error; |
|
} |
|
} else { |
|
theResp.assistant = await this.handle_response_oneshot(resp, apiEP); |
|
} |
|
if (gMe.bTrimGarbage) { |
|
let origMsg = theResp.assistant; |
|
theResp.assistant = du.trim_garbage_at_end(origMsg); |
|
theResp.trimmed = origMsg.substring(theResp.assistant.length); |
|
} |
|
this.add(Roles.Assistant, theResp.assistant); |
|
return theResp; |
|
} |
|
|
|
} |
|
|
|
|
|
class MultiChatUI { |
|
|
|
constructor() { |
|
|
|
this.simpleChats = {}; |
|
|
|
this.curChatId = ""; |
|
|
|
|
|
this.elInSystem = (document.getElementById("system-in")); |
|
this.elDivChat = (document.getElementById("chat-div")); |
|
this.elBtnUser = (document.getElementById("user-btn")); |
|
this.elInUser = (document.getElementById("user-in")); |
|
this.elDivHeading = (document.getElementById("heading")); |
|
this.elDivSessions = (document.getElementById("sessions-div")); |
|
this.elBtnSettings = (document.getElementById("settings")); |
|
|
|
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.elDivHeading, "heading"); |
|
this.validate_element(this.elDivChat, "sessions-div"); |
|
this.validate_element(this.elBtnSettings, "settings"); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
validate_element(el, msgTag) { |
|
if (el == null) { |
|
throw Error(`ERRR:SimpleChat:MCUI:${msgTag} element missing in html...`); |
|
} else { |
|
console.debug(`INFO:SimpleChat:MCUI:${msgTag} Id[${el.id}] Name[${el["name"]}]`); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ui_reset_userinput() { |
|
this.elInUser.value = ""; |
|
this.elInUser.disabled = false; |
|
this.elInUser.focus(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setup_ui(defaultChatId, bSwitchSession=false) { |
|
|
|
this.curChatId = defaultChatId; |
|
if (bSwitchSession) { |
|
this.handle_session_switch(this.curChatId); |
|
} |
|
|
|
this.elBtnSettings.addEventListener("click", (ev)=>{ |
|
this.elDivChat.replaceChildren(); |
|
gMe.show_settings(this.elDivChat); |
|
}); |
|
|
|
this.elBtnUser.addEventListener("click", (ev)=>{ |
|
if (this.elInUser.disabled) { |
|
return; |
|
} |
|
this.handle_user_submit(this.curChatId, gMe.apiEP).catch((reason)=>{ |
|
let msg = `ERRR:SimpleChat\nMCUI:HandleUserSubmit:${this.curChatId}\n${reason.name}:${reason.message}`; |
|
console.error(msg.replace("\n", ":")); |
|
alert(msg); |
|
this.ui_reset_userinput(); |
|
}); |
|
}); |
|
|
|
this.elInUser.addEventListener("keyup", (ev)=> { |
|
|
|
|
|
if ((ev.key === "Enter") && (!ev.shiftKey)) { |
|
let value = this.elInUser.value; |
|
this.elInUser.value = value.substring(0,value.length-1); |
|
this.elBtnUser.click(); |
|
ev.preventDefault(); |
|
} |
|
}); |
|
|
|
this.elInSystem.addEventListener("keyup", (ev)=> { |
|
|
|
|
|
if ((ev.key === "Enter") && (!ev.shiftKey)) { |
|
let value = this.elInSystem.value; |
|
this.elInSystem.value = value.substring(0,value.length-1); |
|
let chat = this.simpleChats[this.curChatId]; |
|
chat.add_system_anytime(this.elInSystem.value, this.curChatId); |
|
chat.show(this.elDivChat); |
|
ev.preventDefault(); |
|
} |
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
new_chat_session(chatId, bSwitchSession=false) { |
|
this.simpleChats[chatId] = new SimpleChat(chatId); |
|
if (bSwitchSession) { |
|
this.handle_session_switch(chatId); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async handle_user_submit(chatId, apiEP) { |
|
|
|
let chat = this.simpleChats[chatId]; |
|
|
|
|
|
|
|
|
|
|
|
if ((apiEP == ApiEP.Type.Completion) && (gMe.bCompletionFreshChatAlways)) { |
|
chat.clear(); |
|
} |
|
|
|
chat.add_system_anytime(this.elInSystem.value, chatId); |
|
|
|
let content = this.elInUser.value; |
|
if (!chat.add(Roles.User, content)) { |
|
console.debug(`WARN:SimpleChat:MCUI:${chatId}:HandleUserSubmit:Ignoring empty user input...`); |
|
return; |
|
} |
|
chat.show(this.elDivChat); |
|
|
|
let theUrl = ApiEP.Url(gMe.baseURL, apiEP); |
|
let theBody = chat.request_jsonstr(apiEP); |
|
|
|
this.elInUser.value = "working..."; |
|
this.elInUser.disabled = true; |
|
console.debug(`DBUG:SimpleChat:MCUI:${chatId}:HandleUserSubmit:${theUrl}:ReqBody:${theBody}`); |
|
let theHeaders = chat.fetch_headers(apiEP); |
|
let resp = await fetch(theUrl, { |
|
method: "POST", |
|
headers: theHeaders, |
|
body: theBody, |
|
}); |
|
|
|
let theResp = await chat.handle_response(resp, apiEP, this.elDivChat); |
|
if (chatId == this.curChatId) { |
|
chat.show(this.elDivChat); |
|
if (theResp.trimmed.length > 0) { |
|
let p = ui.el_create_append_p(`TRIMMED:${theResp.trimmed}`, this.elDivChat); |
|
p.className="role-trim"; |
|
} |
|
} else { |
|
console.debug(`DBUG:SimpleChat:MCUI:HandleUserSubmit:ChatId has changed:[${chatId}] [${this.curChatId}]`); |
|
} |
|
this.ui_reset_userinput(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
show_sessions(elDiv=undefined) { |
|
if (!elDiv) { |
|
elDiv = this.elDivSessions; |
|
} |
|
elDiv.replaceChildren(); |
|
|
|
let btnNew = ui.el_create_button("New CHAT", (ev)=> { |
|
if (this.elInUser.disabled) { |
|
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("INFO:SimpleChat\nMCUI:NewChat\nEnter id for new chat session", chatId); |
|
if (!chatIdGot) { |
|
console.error("ERRR:SimpleChat:MCUI:NewChat:Skipping based on user request..."); |
|
return; |
|
} |
|
this.new_chat_session(chatIdGot, true); |
|
this.create_session_btn(elDiv, chatIdGot); |
|
ui.el_children_config_class(elDiv, chatIdGot, "session-selected", ""); |
|
}); |
|
elDiv.appendChild(btnNew); |
|
|
|
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) { |
|
let btn = ui.el_create_button(cid, (ev)=>{ |
|
let target = (ev.target); |
|
console.debug(`DBUG:SimpleChat:MCUI:SessionClick:${target.id}`); |
|
if (this.elInUser.disabled) { |
|
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); |
|
ui.el_children_config_class(elDiv, target.id, "session-selected", ""); |
|
}); |
|
elDiv.appendChild(btn); |
|
return btn; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
async handle_session_switch(chatId) { |
|
let chat = this.simpleChats[chatId]; |
|
if (chat == undefined) { |
|
console.error(`ERRR:SimpleChat:MCUI:HandleSessionSwitch:${chatId} missing...`); |
|
return; |
|
} |
|
this.elInSystem.value = chat.get_system_latest(); |
|
this.elInUser.value = ""; |
|
chat.show(this.elDivChat); |
|
this.elInUser.focus(); |
|
this.curChatId = chatId; |
|
console.log(`INFO:SimpleChat:MCUI:HandleSessionSwitch:${chatId} entered...`); |
|
} |
|
|
|
} |
|
|
|
|
|
class Me { |
|
|
|
constructor() { |
|
this.baseURL = "http://127.0.0.1:8080"; |
|
this.defaultChatIds = [ "Default", "Other" ]; |
|
this.multiChat = new MultiChatUI(); |
|
this.bStream = true; |
|
this.bCompletionFreshChatAlways = true; |
|
this.bCompletionInsertStandardRolePrefix = false; |
|
this.bTrimGarbage = true; |
|
this.iRecentUserMsgCnt = 2; |
|
this.sRecentUserMsgCnt = { |
|
"Full": -1, |
|
"Last0": 1, |
|
"Last1": 2, |
|
"Last2": 3, |
|
"Last4": 5, |
|
}; |
|
this.apiEP = ApiEP.Type.Chat; |
|
this.headers = { |
|
"Content-Type": "application/json", |
|
"Authorization": "", |
|
} |
|
|
|
this.apiRequestOptions = { |
|
"model": "gpt-3.5-turbo", |
|
"temperature": 0.7, |
|
"max_tokens": 1024, |
|
"n_predict": 1024, |
|
"cache_prompt": false, |
|
|
|
|
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
debug_disable() { |
|
this.console_debug = console.debug; |
|
console.debug = () => { |
|
|
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
setup_load(div, chat) { |
|
if (!(chat.ods_key() in localStorage)) { |
|
return; |
|
} |
|
div.innerHTML += `<p class="role-system">Restore</p> |
|
<p>Load previously saved chat session, if available</p>`; |
|
let btn = ui.el_create_button(chat.ods_key(), (ev)=>{ |
|
console.log("DBUG:SimpleChat:SC:Load", chat); |
|
chat.load(); |
|
queueMicrotask(()=>{ |
|
chat.show(div); |
|
this.multiChat.elInSystem.value = chat.get_system_latest(); |
|
}); |
|
}); |
|
div.appendChild(btn); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
show_info(elDiv, bAll=false) { |
|
|
|
let p = ui.el_create_append_p("Settings (devel-tools-console document[gMe])", elDiv); |
|
p.className = "role-system"; |
|
|
|
if (bAll) { |
|
|
|
ui.el_create_append_p(`baseURL:${this.baseURL}`, elDiv); |
|
|
|
ui.el_create_append_p(`Authorization:${this.headers["Authorization"]}`, elDiv); |
|
|
|
ui.el_create_append_p(`bStream:${this.bStream}`, elDiv); |
|
|
|
ui.el_create_append_p(`bTrimGarbage:${this.bTrimGarbage}`, elDiv); |
|
|
|
ui.el_create_append_p(`ApiEndPoint:${this.apiEP}`, elDiv); |
|
|
|
ui.el_create_append_p(`iRecentUserMsgCnt:${this.iRecentUserMsgCnt}`, elDiv); |
|
|
|
ui.el_create_append_p(`bCompletionFreshChatAlways:${this.bCompletionFreshChatAlways}`, elDiv); |
|
|
|
ui.el_create_append_p(`bCompletionInsertStandardRolePrefix:${this.bCompletionInsertStandardRolePrefix}`, elDiv); |
|
|
|
} |
|
|
|
ui.el_create_append_p(`apiRequestOptions:${JSON.stringify(this.apiRequestOptions, null, " - ")}`, elDiv); |
|
ui.el_create_append_p(`headers:${JSON.stringify(this.headers, null, " - ")}`, elDiv); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
show_settings_apirequestoptions(elDiv) { |
|
let typeDict = { |
|
"string": "text", |
|
"number": "number", |
|
}; |
|
let fs = document.createElement("fieldset"); |
|
let legend = document.createElement("legend"); |
|
legend.innerText = "ApiRequestOptions"; |
|
fs.appendChild(legend); |
|
elDiv.appendChild(fs); |
|
for(const k in this.apiRequestOptions) { |
|
let val = this.apiRequestOptions[k]; |
|
let type = typeof(val); |
|
if (((type == "string") || (type == "number"))) { |
|
let inp = ui.el_creatediv_input(`Set${k}`, k, typeDict[type], this.apiRequestOptions[k], (val)=>{ |
|
if (type == "number") { |
|
val = Number(val); |
|
} |
|
this.apiRequestOptions[k] = val; |
|
}); |
|
fs.appendChild(inp.div); |
|
} else if (type == "boolean") { |
|
let bbtn = ui.el_creatediv_boolbutton(`Set{k}`, k, {true: "true", false: "false"}, val, (userVal)=>{ |
|
this.apiRequestOptions[k] = userVal; |
|
}); |
|
fs.appendChild(bbtn.div); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
show_settings(elDiv) { |
|
|
|
let inp = ui.el_creatediv_input("SetBaseURL", "BaseURL", "text", this.baseURL, (val)=>{ |
|
this.baseURL = val; |
|
}); |
|
elDiv.appendChild(inp.div); |
|
|
|
inp = ui.el_creatediv_input("SetAuthorization", "Authorization", "text", this.headers["Authorization"], (val)=>{ |
|
this.headers["Authorization"] = val; |
|
}); |
|
inp.el.placeholder = "Bearer OPENAI_API_KEY"; |
|
elDiv.appendChild(inp.div); |
|
|
|
let bb = ui.el_creatediv_boolbutton("SetStream", "Stream", {true: "[+] yes stream", false: "[-] do oneshot"}, this.bStream, (val)=>{ |
|
this.bStream = val; |
|
}); |
|
elDiv.appendChild(bb.div); |
|
|
|
bb = ui.el_creatediv_boolbutton("SetTrimGarbage", "TrimGarbage", {true: "[+] yes trim", false: "[-] dont trim"}, this.bTrimGarbage, (val)=>{ |
|
this.bTrimGarbage = val; |
|
}); |
|
elDiv.appendChild(bb.div); |
|
|
|
this.show_settings_apirequestoptions(elDiv); |
|
|
|
let sel = ui.el_creatediv_select("SetApiEP", "ApiEndPoint", ApiEP.Type, this.apiEP, (val)=>{ |
|
this.apiEP = ApiEP.Type[val]; |
|
}); |
|
elDiv.appendChild(sel.div); |
|
|
|
sel = ui.el_creatediv_select("SetChatHistoryInCtxt", "ChatHistoryInCtxt", this.sRecentUserMsgCnt, this.iRecentUserMsgCnt, (val)=>{ |
|
this.iRecentUserMsgCnt = this.sRecentUserMsgCnt[val]; |
|
}); |
|
elDiv.appendChild(sel.div); |
|
|
|
bb = ui.el_creatediv_boolbutton("SetCompletionFreshChatAlways", "CompletionFreshChatAlways", {true: "[+] yes fresh", false: "[-] no, with history"}, this.bCompletionFreshChatAlways, (val)=>{ |
|
this.bCompletionFreshChatAlways = val; |
|
}); |
|
elDiv.appendChild(bb.div); |
|
|
|
bb = ui.el_creatediv_boolbutton("SetCompletionInsertStandardRolePrefix", "CompletionInsertStandardRolePrefix", {true: "[+] yes insert", false: "[-] dont insert"}, this.bCompletionInsertStandardRolePrefix, (val)=>{ |
|
this.bCompletionInsertStandardRolePrefix = val; |
|
}); |
|
elDiv.appendChild(bb.div); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let gMe; |
|
|
|
function startme() { |
|
console.log("INFO:SimpleChat:StartMe:Starting..."); |
|
gMe = new Me(); |
|
gMe.debug_disable(); |
|
document["gMe"] = gMe; |
|
document["du"] = du; |
|
for (let cid of gMe.defaultChatIds) { |
|
gMe.multiChat.new_chat_session(cid); |
|
} |
|
gMe.multiChat.setup_ui(gMe.defaultChatIds[0], true); |
|
gMe.multiChat.show_sessions(); |
|
} |
|
|
|
document.addEventListener("DOMContentLoaded", startme); |
|
|