Spaces:
Sleeping
Sleeping
feat(conv): let user switch models on conversations with deprecated models (#1462)
Browse files* feat(conv): let user switch models on conversations with deprecated models
* lint
* fix checks
src/lib/components/chat/ChatWindow.svelte
CHANGED
@@ -35,6 +35,7 @@
|
|
35 |
import UploadedFile from "./UploadedFile.svelte";
|
36 |
import { useSettingsStore } from "$lib/stores/settings";
|
37 |
import type { ToolFront } from "$lib/types/Tool";
|
|
|
38 |
|
39 |
export let messages: Message[] = [];
|
40 |
export let loading = false;
|
@@ -279,6 +280,9 @@
|
|
279 |
on:vote
|
280 |
on:continue
|
281 |
/>
|
|
|
|
|
|
|
282 |
</div>
|
283 |
{:else if pending}
|
284 |
<ChatMessage
|
@@ -403,9 +407,7 @@
|
|
403 |
<ChatInput value="Sorry, something went wrong. Please try again." disabled={true} />
|
404 |
{:else}
|
405 |
<ChatInput
|
406 |
-
placeholder={isReadOnly
|
407 |
-
? "This conversation is read-only. Start a new one to continue!"
|
408 |
-
: "Ask anything"}
|
409 |
bind:value={message}
|
410 |
on:submit={handleSubmit}
|
411 |
on:beforeinput={(ev) => {
|
|
|
35 |
import UploadedFile from "./UploadedFile.svelte";
|
36 |
import { useSettingsStore } from "$lib/stores/settings";
|
37 |
import type { ToolFront } from "$lib/types/Tool";
|
38 |
+
import ModelSwitch from "./ModelSwitch.svelte";
|
39 |
|
40 |
export let messages: Message[] = [];
|
41 |
export let loading = false;
|
|
|
280 |
on:vote
|
281 |
on:continue
|
282 |
/>
|
283 |
+
{#if isReadOnly}
|
284 |
+
<ModelSwitch {models} {currentModel} />
|
285 |
+
{/if}
|
286 |
</div>
|
287 |
{:else if pending}
|
288 |
<ChatMessage
|
|
|
407 |
<ChatInput value="Sorry, something went wrong. Please try again." disabled={true} />
|
408 |
{:else}
|
409 |
<ChatInput
|
410 |
+
placeholder={isReadOnly ? "This conversation is read-only." : "Ask anything"}
|
|
|
|
|
411 |
bind:value={message}
|
412 |
on:submit={handleSubmit}
|
413 |
on:beforeinput={(ev) => {
|
src/lib/components/chat/ModelSwitch.svelte
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts">
|
2 |
+
import { invalidateAll } from "$app/navigation";
|
3 |
+
import { page } from "$app/stores";
|
4 |
+
import { base } from "$app/paths";
|
5 |
+
import type { Model } from "$lib/types/Model";
|
6 |
+
|
7 |
+
export let models: Model[];
|
8 |
+
export let currentModel: Model;
|
9 |
+
|
10 |
+
let selectedModelId = models.map((m) => m.id).includes(currentModel.id)
|
11 |
+
? currentModel.id
|
12 |
+
: models[0].id;
|
13 |
+
|
14 |
+
async function handleModelChange() {
|
15 |
+
if (!$page.params.id) return;
|
16 |
+
|
17 |
+
try {
|
18 |
+
const response = await fetch(`${base}/conversation/${$page.params.id}`, {
|
19 |
+
method: "PATCH",
|
20 |
+
headers: {
|
21 |
+
"Content-Type": "application/json",
|
22 |
+
},
|
23 |
+
body: JSON.stringify({ model: selectedModelId }),
|
24 |
+
});
|
25 |
+
|
26 |
+
if (!response.ok) {
|
27 |
+
throw new Error("Failed to update model");
|
28 |
+
}
|
29 |
+
|
30 |
+
await invalidateAll();
|
31 |
+
} catch (error) {
|
32 |
+
console.error(error);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
</script>
|
36 |
+
|
37 |
+
<div
|
38 |
+
class="mx-auto mt-0 flex w-fit flex-col items-center justify-center gap-2 rounded-lg border border-gray-200 bg-gray-500/20 p-4 dark:border-gray-800"
|
39 |
+
>
|
40 |
+
<span>
|
41 |
+
This model is no longer available. Switch to a new one to continue this conversation:
|
42 |
+
</span>
|
43 |
+
<div class="flex items-center space-x-2">
|
44 |
+
<select
|
45 |
+
bind:value={selectedModelId}
|
46 |
+
class="rounded-md bg-gray-100 px-2 py-1 dark:bg-gray-900 max-sm:max-w-32"
|
47 |
+
>
|
48 |
+
{#each models as model}
|
49 |
+
<option value={model.id}>{model.name}</option>
|
50 |
+
{/each}
|
51 |
+
</select>
|
52 |
+
<button
|
53 |
+
on:click={handleModelChange}
|
54 |
+
disabled={selectedModelId === currentModel.id}
|
55 |
+
class="rounded-md bg-gray-100 px-2 py-1 dark:bg-gray-900"
|
56 |
+
>
|
57 |
+
Accept
|
58 |
+
</button>
|
59 |
+
</div>
|
60 |
+
</div>
|
src/lib/server/models.ts
CHANGED
@@ -321,7 +321,7 @@ export const models: ProcessedModel[] = await Promise.all(
|
|
321 |
);
|
322 |
|
323 |
// super ugly but not sure how to make typescript happier
|
324 |
-
const validModelIdSchema = z.enum(models.map((m) => m.id) as [string, ...string[]]);
|
325 |
|
326 |
export const defaultModel = models[0];
|
327 |
|
|
|
321 |
);
|
322 |
|
323 |
// super ugly but not sure how to make typescript happier
|
324 |
+
export const validModelIdSchema = z.enum(models.map((m) => m.id) as [string, ...string[]]);
|
325 |
|
326 |
export const defaultModel = models[0];
|
327 |
|
src/routes/conversation/[id]/+server.ts
CHANGED
@@ -2,7 +2,7 @@ import { env } from "$env/dynamic/private";
|
|
2 |
import { startOfHour } from "date-fns";
|
3 |
import { authCondition, requiresUser } from "$lib/server/auth";
|
4 |
import { collections } from "$lib/server/database";
|
5 |
-
import { models } from "$lib/server/models";
|
6 |
import { ERROR_MESSAGES } from "$lib/stores/errors";
|
7 |
import type { Message } from "$lib/types/Message";
|
8 |
import { error } from "@sveltejs/kit";
|
@@ -513,8 +513,11 @@ export async function DELETE({ locals, params }) {
|
|
513 |
}
|
514 |
|
515 |
export async function PATCH({ request, locals, params }) {
|
516 |
-
const
|
517 |
-
.object({
|
|
|
|
|
|
|
518 |
.parse(await request.json());
|
519 |
|
520 |
const convId = new ObjectId(params.id);
|
@@ -533,9 +536,7 @@ export async function PATCH({ request, locals, params }) {
|
|
533 |
_id: convId,
|
534 |
},
|
535 |
{
|
536 |
-
$set:
|
537 |
-
title,
|
538 |
-
},
|
539 |
}
|
540 |
);
|
541 |
|
|
|
2 |
import { startOfHour } from "date-fns";
|
3 |
import { authCondition, requiresUser } from "$lib/server/auth";
|
4 |
import { collections } from "$lib/server/database";
|
5 |
+
import { models, validModelIdSchema } from "$lib/server/models";
|
6 |
import { ERROR_MESSAGES } from "$lib/stores/errors";
|
7 |
import type { Message } from "$lib/types/Message";
|
8 |
import { error } from "@sveltejs/kit";
|
|
|
513 |
}
|
514 |
|
515 |
export async function PATCH({ request, locals, params }) {
|
516 |
+
const values = z
|
517 |
+
.object({
|
518 |
+
title: z.string().trim().min(1).max(100).optional(),
|
519 |
+
model: validModelIdSchema.optional(),
|
520 |
+
})
|
521 |
.parse(await request.json());
|
522 |
|
523 |
const convId = new ObjectId(params.id);
|
|
|
536 |
_id: convId,
|
537 |
},
|
538 |
{
|
539 |
+
$set: values,
|
|
|
|
|
540 |
}
|
541 |
);
|
542 |
|