display system prompt

This commit is contained in:
Charlotte Som 2025-02-27 07:54:53 +00:00
parent 43f44fcab4
commit baedcbaab7
4 changed files with 41 additions and 18 deletions

View file

@ -11,25 +11,17 @@ async function nav() {
const conversations = await fetch("/api/conversation").then(r => r.json()); const conversations = await fetch("/api/conversation").then(r => r.json());
for (const conversation of conversations) { for (const conversation of conversations) {
const button = <button type="button">{conversation.name}</button>; const button = (
button.addEventListener("click", e => { <button type="button" _onclick={e => (e.preventDefault(), route.set(conversation.id))}>
e.preventDefault(); {conversation.name}
route.set(conversation.id); </button>
}); );
nav.append(button); nav.append(button);
} }
nav.append( nav.append(
<button <button type="button" _onclick={e => (e.preventDefault(), route.set("new"))}>
type="button"
_tap={b =>
b.addEventListener("click", e => {
e.preventDefault();
route.set("new");
})
}
>
new new
</button>, </button>,
); );
@ -105,6 +97,14 @@ function conversationUI(id: string) {
inFlightMessages.delete(message.d); inFlightMessages.delete(message.d);
} else if ("n" in message) { } else if ("n" in message) {
name.set(message.n); name.set(message.n);
} else if ("sys" in message) {
chatlog.append(<article className="system">{message.sys}</article>);
} else if ("err" in message) {
chatlog.append(<article className="system error">{message.err}</article>);
if ("r" in message) {
inFlightMessages.get(message.r)?.element?.remove();
inFlightMessages.delete(message.r);
}
} }
if (scrolledToBottom) chatlog.scrollTop = chatlog.scrollHeight - chatlog.clientHeight; if (scrolledToBottom) chatlog.scrollTop = chatlog.scrollHeight - chatlog.clientHeight;
@ -115,6 +115,7 @@ function conversationUI(id: string) {
<input type="text" placeholder="Enter a prompt…" required /> <input type="text" placeholder="Enter a prompt…" required />
</form> </form>
); );
// TODO: support multiline input via shift + enter
const input = form.querySelector("input")!; const input = form.querySelector("input")!;
form.addEventListener("submit", e => { form.addEventListener("submit", e => {
e.preventDefault(); e.preventDefault();

View file

@ -6,6 +6,7 @@
--alpha-text: 1; --alpha-text: 1;
line-height: 1.25; line-height: 1.25;
font-size: 1.25rem;
} }
::selection { ::selection {
@ -86,6 +87,17 @@ main,
color: rgb(var(--color-text) / 0.5); color: rgb(var(--color-text) / 0.5);
} }
article.system:not(.error) {
font-size: 0.5em;
font-family: var(--font-mono);
color: rgb(var(--color-fg) / 0.5);
}
article.system.error {
font-family: var(--font-mono);
background-color: rgb(127 0 0 / 0.5);
}
summary { summary {
margin-bottom: 0; margin-bottom: 0;
color: rgb(var(--color-accent) / 1); color: rgb(var(--color-accent) / 1);

View file

@ -8,7 +8,7 @@
"run": "deno task client:build --watch & deno task server:run" "run": "deno task client:build --watch & deno task server:run"
}, },
"imports": { "imports": {
"@char/aftercare": "jsr:@char/aftercare@^0.2.0" "@char/aftercare": "jsr:@char/aftercare@^0.3.0"
}, },
"compilerOptions": { "compilerOptions": {
"lib": ["deno.window", "deno.unstable", "dom"], "lib": ["deno.window", "deno.unstable", "dom"],

View file

@ -45,22 +45,32 @@ async def connect_to_conversation(ws: WebSocket):
if not response._done: continue if not response._done: continue
if response.prompt.system: if response.prompt.system:
system_prompt = None system_prompt = None
await ws.send_text(json({"sys": response.prompt.system}))
await ws.send_text(json({"u": response.prompt.prompt})) # user await ws.send_text(json({"u": response.prompt.prompt})) # user
await ws.send_text(json({"f": response.text_or_raise()})) # full await ws.send_text(json({"f": response.text_or_raise()})) # full
await ws.send_text(json({"n": conversation.name})) if conversation.name:
await ws.send_text(json({"n": conversation.name}))
if conversation_id == "new": if conversation_id == "new":
await ws.send_text(json({"i": conversation.id})) await ws.send_text(json({"i": conversation.id}))
async for message in ws.iter_text(): async for message in ws.iter_text():
if system_prompt:
await ws.send_text(json({"sys": system_prompt}))
response = conversation.prompt(message, system=system_prompt, stream=True) response = conversation.prompt(message, system=system_prompt, stream=True)
system_prompt = None system_prompt = None
response_tid = tid_now() response_tid = tid_now()
await ws.send_text(json({"u": message})) await ws.send_text(json({"u": message}))
await ws.send_text(json({"s": response_tid})) # start await ws.send_text(json({"s": response_tid})) # start
async for chunk in response: try:
await ws.send_text(json({"r": response_tid, "c": chunk})) async for chunk in response:
await ws.send_text(json({"r": response_tid, "c": chunk}))
except BaseException as e:
await ws.send_text(json({"err": str(e), "r": response_tid}))
await ws.send_text(json({"d": response_tid})) # done await ws.send_text(json({"d": response_tid})) # done
(await response.to_sync_response()).log_to_db(db) (await response.to_sync_response()).log_to_db(db)
if conversation.name:
await ws.send_text(json({"n": conversation.name}))