Chat improvements (#23195)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

* Support token streaming stats

* Propogate streaming token stats to chat calls

* Show token stats for each image

* Add settings to handle token stats and other options

* i18n

* Use select

* Improve mobile layout and spacing
This commit is contained in:
Nicolas Mowen
2026-05-14 12:05:38 -05:00
committed by GitHub
parent 78fc472026
commit d9c1ea908d
14 changed files with 542 additions and 128 deletions
+33 -2
View File
@@ -1,4 +1,4 @@
import type { ChatMessage, ToolCall } from "@/types/chat";
import type { ChatMessage, ChatStats, ToolCall } from "@/types/chat";
export type StreamChatCallbacks = {
/** Update the messages array (e.g. pass to setState). */
@@ -7,14 +7,27 @@ export type StreamChatCallbacks = {
onError: (message: string) => void;
/** Called when the stream finishes (success or error). */
onDone: () => void;
/** Called when the stream emits token/timing stats. The stats are also
* attached to the last assistant message in updateMessages, so consumers
* can usually rely on the message itself rather than wiring this up. */
onStats?: (stats: ChatStats) => void;
/** Message used when fetch throws and no server error is available. */
defaultErrorMessage?: string;
};
type StatsChunk = {
type: "stats";
prompt_tokens?: number;
completion_tokens?: number;
completion_duration_ms?: number;
tokens_per_second?: number;
};
type StreamChunk =
| { type: "error"; error: string }
| { type: "tool_calls"; tool_calls: ToolCall[] }
| { type: "content"; delta: string };
| { type: "content"; delta: string }
| StatsChunk;
/**
* POST to chat/completion with stream: true, parse NDJSON stream, and invoke
@@ -31,6 +44,7 @@ export async function streamChatCompletion(
updateMessages,
onError,
onDone,
onStats,
defaultErrorMessage = "Something went wrong. Please try again.",
} = callbacks;
@@ -95,6 +109,23 @@ export async function streamChatCompletion(
});
return "continue";
}
if (data.type === "stats") {
const stats: ChatStats = {
promptTokens: data.prompt_tokens,
completionTokens: data.completion_tokens,
completionDurationMs: data.completion_duration_ms,
tokensPerSecond: data.tokens_per_second,
};
updateMessages((prev) => {
const next = [...prev];
const lastMsg = next[next.length - 1];
if (lastMsg?.role === "assistant")
next[next.length - 1] = { ...lastMsg, stats };
return next;
});
onStats?.(stats);
return "continue";
}
return "continue";
};