Spaces:
Running
Running
Add "disable streaming tokens" settings & remove media query (#1299)
Browse files- src/lib/components/chat/ChatMessage.svelte +5 -10
- src/lib/stores/settings.ts +1 -0
- src/lib/types/Settings.ts +4 -1
- src/lib/utils/isReduceMotion.ts +0 -5
- src/routes/+layout.server.ts +1 -0
- src/routes/conversation/[id]/+page.svelte +1 -4
- src/routes/settings/(nav)/+page.svelte +8 -0
- src/routes/settings/(nav)/+server.ts +3 -2
src/lib/components/chat/ChatMessage.svelte
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
import { marked, type MarkedOptions } from "marked";
|
3 |
import markedKatex from "marked-katex-extension";
|
4 |
import type { Message, MessageFile } from "$lib/types/Message";
|
5 |
-
import { afterUpdate, createEventDispatcher,
|
6 |
import { deepestChild } from "$lib/utils/deepestChild";
|
7 |
import { page } from "$app/stores";
|
8 |
|
@@ -30,9 +30,9 @@
|
|
30 |
} from "$lib/types/MessageUpdate";
|
31 |
import { base } from "$app/paths";
|
32 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
33 |
-
import { isReducedMotion } from "$lib/utils/isReduceMotion";
|
34 |
import Modal from "../Modal.svelte";
|
35 |
import ToolUpdate from "./ToolUpdate.svelte";
|
|
|
36 |
|
37 |
function sanitizeMd(md: string) {
|
38 |
let ret = md
|
@@ -80,9 +80,6 @@
|
|
80 |
let isCopied = false;
|
81 |
|
82 |
let initialized = false;
|
83 |
-
|
84 |
-
let reducedMotionMode = false;
|
85 |
-
|
86 |
const renderer = new marked.Renderer();
|
87 |
// For code blocks with simple backticks
|
88 |
renderer.codespan = (code) => {
|
@@ -118,12 +115,10 @@
|
|
118 |
$: emptyLoad =
|
119 |
!message.content && (webSearchIsDone || (searchUpdates && searchUpdates.length === 0));
|
120 |
|
121 |
-
|
122 |
-
reducedMotionMode = isReducedMotion(window);
|
123 |
-
});
|
124 |
|
125 |
afterUpdate(() => {
|
126 |
-
if (
|
127 |
return;
|
128 |
}
|
129 |
|
@@ -301,7 +296,7 @@
|
|
301 |
class="prose max-w-none max-sm:prose-sm dark:prose-invert prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
302 |
bind:this={contentEl}
|
303 |
>
|
304 |
-
{#if isLast && loading &&
|
305 |
<IconLoading classNames="loading inline ml-2 first:ml-0" />
|
306 |
{/if}
|
307 |
{#each tokens as token}
|
|
|
2 |
import { marked, type MarkedOptions } from "marked";
|
3 |
import markedKatex from "marked-katex-extension";
|
4 |
import type { Message, MessageFile } from "$lib/types/Message";
|
5 |
+
import { afterUpdate, createEventDispatcher, tick } from "svelte";
|
6 |
import { deepestChild } from "$lib/utils/deepestChild";
|
7 |
import { page } from "$app/stores";
|
8 |
|
|
|
30 |
} from "$lib/types/MessageUpdate";
|
31 |
import { base } from "$app/paths";
|
32 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
|
|
33 |
import Modal from "../Modal.svelte";
|
34 |
import ToolUpdate from "./ToolUpdate.svelte";
|
35 |
+
import { useSettingsStore } from "$lib/stores/settings";
|
36 |
|
37 |
function sanitizeMd(md: string) {
|
38 |
let ret = md
|
|
|
80 |
let isCopied = false;
|
81 |
|
82 |
let initialized = false;
|
|
|
|
|
|
|
83 |
const renderer = new marked.Renderer();
|
84 |
// For code blocks with simple backticks
|
85 |
renderer.codespan = (code) => {
|
|
|
115 |
$: emptyLoad =
|
116 |
!message.content && (webSearchIsDone || (searchUpdates && searchUpdates.length === 0));
|
117 |
|
118 |
+
const settings = useSettingsStore();
|
|
|
|
|
119 |
|
120 |
afterUpdate(() => {
|
121 |
+
if ($settings.disableStream) {
|
122 |
return;
|
123 |
}
|
124 |
|
|
|
296 |
class="prose max-w-none max-sm:prose-sm dark:prose-invert prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
297 |
bind:this={contentEl}
|
298 |
>
|
299 |
+
{#if isLast && loading && $settings.disableStream}
|
300 |
<IconLoading classNames="loading inline ml-2 first:ml-0" />
|
301 |
{/if}
|
302 |
{#each tokens as token}
|
src/lib/stores/settings.ts
CHANGED
@@ -16,6 +16,7 @@ type SettingsStore = {
|
|
16 |
recentlySaved: boolean;
|
17 |
assistants: Array<ObjectId | string>;
|
18 |
tools?: Record<string, boolean>;
|
|
|
19 |
};
|
20 |
|
21 |
type SettingsStoreWritable = Writable<SettingsStore> & {
|
|
|
16 |
recentlySaved: boolean;
|
17 |
assistants: Array<ObjectId | string>;
|
18 |
tools?: Record<string, boolean>;
|
19 |
+
disableStream: boolean;
|
20 |
};
|
21 |
|
22 |
type SettingsStoreWritable = Writable<SettingsStore> & {
|
src/lib/types/Settings.ts
CHANGED
@@ -22,8 +22,10 @@ export interface Settings extends Timestamps {
|
|
22 |
|
23 |
assistants?: Assistant["_id"][];
|
24 |
tools?: Record<string, boolean>;
|
|
|
25 |
}
|
26 |
|
|
|
27 |
// TODO: move this to a constant file along with other constants
|
28 |
export const DEFAULT_SETTINGS = {
|
29 |
shareConversationsWithModelAuthors: true,
|
@@ -32,4 +34,5 @@ export const DEFAULT_SETTINGS = {
|
|
32 |
customPrompts: {},
|
33 |
assistants: [],
|
34 |
tools: {},
|
35 |
-
|
|
|
|
22 |
|
23 |
assistants?: Assistant["_id"][];
|
24 |
tools?: Record<string, boolean>;
|
25 |
+
disableStream: boolean;
|
26 |
}
|
27 |
|
28 |
+
export type SettingsEditable = Omit<Settings, "ethicsModalAcceptedAt" | "createdAt" | "updatedAt">;
|
29 |
// TODO: move this to a constant file along with other constants
|
30 |
export const DEFAULT_SETTINGS = {
|
31 |
shareConversationsWithModelAuthors: true,
|
|
|
34 |
customPrompts: {},
|
35 |
assistants: [],
|
36 |
tools: {},
|
37 |
+
disableStream: false,
|
38 |
+
} satisfies SettingsEditable;
|
src/lib/utils/isReduceMotion.ts
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
export function isReducedMotion(window: Window) {
|
2 |
-
const { matchMedia } = window;
|
3 |
-
|
4 |
-
return matchMedia("(prefers-reduced-motion: reduce)").matches;
|
5 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
src/routes/+layout.server.ts
CHANGED
@@ -147,6 +147,7 @@ export const load: LayoutServerLoad = async ({ locals, depends }) => {
|
|
147 |
customPrompts: settings?.customPrompts ?? {},
|
148 |
assistants: userAssistants,
|
149 |
tools: settings?.tools ?? {},
|
|
|
150 |
},
|
151 |
models: models.map((model) => ({
|
152 |
id: model.id,
|
|
|
147 |
customPrompts: settings?.customPrompts ?? {},
|
148 |
assistants: userAssistants,
|
149 |
tools: settings?.tools ?? {},
|
150 |
+
disableStream: settings?.disableStream ?? DEFAULT_SETTINGS.disableStream,
|
151 |
},
|
152 |
models: models.map((model) => ({
|
153 |
id: model.id,
|
src/routes/conversation/[id]/+page.svelte
CHANGED
@@ -23,7 +23,6 @@
|
|
23 |
import { fetchMessageUpdates } from "$lib/utils/messageUpdates";
|
24 |
import { createConvTreeStore } from "$lib/stores/convTree";
|
25 |
import type { v4 } from "uuid";
|
26 |
-
import { isReducedMotion } from "$lib/utils/isReduceMotion.js";
|
27 |
import { useSettingsStore } from "$lib/stores/settings.js";
|
28 |
|
29 |
export let data;
|
@@ -80,8 +79,6 @@
|
|
80 |
$isAborted = false;
|
81 |
loading = true;
|
82 |
pending = true;
|
83 |
-
const reducedMotionMode = isReducedMotion(window);
|
84 |
-
|
85 |
const base64Files = await Promise.all(
|
86 |
(files ?? []).map((file) =>
|
87 |
file2base64(file).then((value) => ({
|
@@ -237,7 +234,7 @@
|
|
237 |
|
238 |
messageUpdates.push(update);
|
239 |
|
240 |
-
if (update.type === MessageUpdateType.Stream &&
|
241 |
messageToWriteTo.content += update.token;
|
242 |
pending = false;
|
243 |
messages = [...messages];
|
|
|
23 |
import { fetchMessageUpdates } from "$lib/utils/messageUpdates";
|
24 |
import { createConvTreeStore } from "$lib/stores/convTree";
|
25 |
import type { v4 } from "uuid";
|
|
|
26 |
import { useSettingsStore } from "$lib/stores/settings.js";
|
27 |
|
28 |
export let data;
|
|
|
79 |
$isAborted = false;
|
80 |
loading = true;
|
81 |
pending = true;
|
|
|
|
|
82 |
const base64Files = await Promise.all(
|
83 |
(files ?? []).map((file) =>
|
84 |
file2base64(file).then((value) => ({
|
|
|
234 |
|
235 |
messageUpdates.push(update);
|
236 |
|
237 |
+
if (update.type === MessageUpdateType.Stream && !$settings.disableStream) {
|
238 |
messageToWriteTo.content += update.token;
|
239 |
pending = false;
|
240 |
messages = [...messages];
|
src/routes/settings/(nav)/+page.svelte
CHANGED
@@ -46,6 +46,14 @@
|
|
46 |
</div>
|
47 |
</label>
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
<div class="mt-12 flex flex-col gap-3">
|
50 |
<a
|
51 |
href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
|
|
|
46 |
</div>
|
47 |
</label>
|
48 |
|
49 |
+
<!-- svelte-ignore a11y-label-has-associated-control -->
|
50 |
+
<label class="mt-6 flex items-center">
|
51 |
+
<Switch name="disableStream" bind:checked={$settings.disableStream} />
|
52 |
+
<div class="inline cursor-pointer select-none items-center gap-2 pl-2">
|
53 |
+
Disable streaming tokens
|
54 |
+
</div>
|
55 |
+
</label>
|
56 |
+
|
57 |
<div class="mt-12 flex flex-col gap-3">
|
58 |
<a
|
59 |
href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
|
src/routes/settings/(nav)/+server.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import { collections } from "$lib/server/database";
|
2 |
import { z } from "zod";
|
3 |
import { authCondition } from "$lib/server/auth";
|
4 |
-
import { DEFAULT_SETTINGS } from "$lib/types/Settings";
|
5 |
|
6 |
export async function POST({ request, locals }) {
|
7 |
const body = await request.json();
|
@@ -16,8 +16,9 @@ export async function POST({ request, locals }) {
|
|
16 |
activeModel: z.string().default(DEFAULT_SETTINGS.activeModel),
|
17 |
customPrompts: z.record(z.string()).default({}),
|
18 |
tools: z.record(z.boolean()).optional(),
|
|
|
19 |
})
|
20 |
-
.parse(body);
|
21 |
|
22 |
await collections.settings.updateOne(
|
23 |
authCondition(locals),
|
|
|
1 |
import { collections } from "$lib/server/database";
|
2 |
import { z } from "zod";
|
3 |
import { authCondition } from "$lib/server/auth";
|
4 |
+
import { DEFAULT_SETTINGS, type SettingsEditable } from "$lib/types/Settings";
|
5 |
|
6 |
export async function POST({ request, locals }) {
|
7 |
const body = await request.json();
|
|
|
16 |
activeModel: z.string().default(DEFAULT_SETTINGS.activeModel),
|
17 |
customPrompts: z.record(z.string()).default({}),
|
18 |
tools: z.record(z.boolean()).optional(),
|
19 |
+
disableStream: z.boolean().default(false),
|
20 |
})
|
21 |
+
.parse(body) satisfies SettingsEditable;
|
22 |
|
23 |
await collections.settings.updateOne(
|
24 |
authCondition(locals),
|