Skip to content

Commit 7bfc845

Browse files
committed
feat: pretty print of model names that have them
1 parent c1a04b9 commit 7bfc845

File tree

9 files changed

+95
-83
lines changed

9 files changed

+95
-83
lines changed

app/components/Chat/Bubble/ChatBubbleRegenerate.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ watch(
8282
userSettingsStore.updateSettings({
8383
model: {
8484
name: model.name,
85+
displayName: model.displayName,
8586
provider: model.provider,
8687
url: model.url,
8788
},
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
<script setup lang="ts">
2-
const props = defineProps<{
3-
model?: {
4-
name: string;
5-
provider: string;
6-
};
2+
import type { Model } from "~/utils/db/local";
3+
4+
defineProps<{
5+
model?: Model;
76
}>();
8-
const currentModelName = computed(() => {
9-
return props.model?.name;
10-
});
117
</script>
128

139
<template>
@@ -17,7 +13,7 @@ const currentModelName = computed(() => {
1713
class="text-(--main-color) scale-90"
1814
/>
1915
<div class="text-(--main-color) text-sm">
20-
{{ currentModelName }}
16+
{{ model.displayName }}
2117
</div>
2218
</div>
2319
</template>

app/components/Chat/ChatInputModel.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ onBeforeUnmount(() => {
4747
/>
4848
<div class="flex items-center gap-1">
4949
<div v-if="currentModel" class="text-sm text-(--main-color)">
50-
{{ currentModel.name }}
50+
{{ currentModel.displayName }}
5151
</div>
5252
<div
5353
v-if="!currentModel && availableModels.length"
@@ -95,6 +95,7 @@ onBeforeUnmount(() => {
9595
userSettingsStore.updateSettings({
9696
model: {
9797
name: model.name,
98+
displayName: model.displayName,
9899
provider: model.provider,
99100
url: model.url,
100101
},
@@ -108,7 +109,7 @@ onBeforeUnmount(() => {
108109
class="text-(--main-color) scale-125"
109110
/>
110111
<div class="flex flex-col overflow-hidden">
111-
<HoverScrollText>{{ model.name }}</HoverScrollText>
112+
<HoverScrollText>{{ model.displayName }}</HoverScrollText>
112113
<div class="text-xs italic text-(--sub-color)">
113114
{{ model.url }}
114115
</div>

app/components/Settings/SettingsAdminModels.vue

Lines changed: 61 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<script setup lang="ts">
2+
import type { Model } from "~/utils/db/local";
3+
24
interface Models {
3-
openai: string[];
4-
gemini: string[];
5-
anthropic: string[];
6-
ollama: Record<string, string[]>;
5+
openai: Model[];
6+
gemini: Model[];
7+
anthropic: Model[];
8+
ollama: Record<string, Model[]>;
79
}
810
const models = ref<Models>({
911
openai: [],
@@ -13,7 +15,7 @@ const models = ref<Models>({
1315
});
1416
async function fetchModels(provider: keyof Models, url?: string) {
1517
if (provider === "ollama" && url) {
16-
const response = await $fetch<{ models: string[] }>(
18+
const response = await $fetch<{ models: Model[] }>(
1719
`/api/models/ollama?url=${encodeURIComponent(url)}`,
1820
);
1921
models.value.ollama[url] = response.models;
@@ -22,66 +24,58 @@ async function fetchModels(provider: keyof Models, url?: string) {
2224
provider === "gemini" ||
2325
provider === "anthropic"
2426
) {
25-
const response = await $fetch<{ models: string[] }>(
27+
const response = await $fetch<{ models: Model[] }>(
2628
`/api/models/${provider}`,
2729
);
28-
console.log(provider, response);
2930
models.value[provider] = response.models;
3031
}
3132
}
3233
const globalSettingsStore = useGlobalSettingsStore();
3334
const availableModels = computed(() => {
3435
return globalSettingsStore.settings.availableModels;
3536
});
36-
function checkAvailableModel(model: string, url?: string) {
37-
if (url) {
37+
function checkAvailableModel(model: Model) {
38+
if (model.url) {
3839
return availableModels.value.some(
39-
(m) => m.name === model && m.provider === "ollama" && m.url === url,
40+
(m) =>
41+
m.name === model.name && m.provider === "ollama" && m.url === model.url,
4042
);
4143
}
42-
return availableModels.value.some((m) => m.name === model);
44+
return availableModels.value.some((m) => m.name === model.name);
4345
}
4446
45-
function addModelToAvailableModels(
46-
model: string,
47-
provider: string,
48-
url?: string,
49-
) {
47+
function addModelToAvailableModels(model: Model) {
5048
globalSettingsStore.updateSettings({
51-
availableModels: [...availableModels.value, { name: model, provider, url }],
49+
availableModels: [...availableModels.value, { ...model }],
5250
});
5351
}
54-
function removeModelFromAvailableModels(
55-
model: string,
56-
provider: string,
57-
url?: string,
58-
) {
52+
function removeModelFromAvailableModels(model: Model) {
5953
globalSettingsStore.updateSettings({
6054
availableModels: availableModels.value.filter(
6155
(m) =>
62-
(m.name !== model && m.url === url) ||
63-
m.name !== model ||
64-
m.provider !== provider ||
65-
m.url !== url,
56+
(m.name !== model.name && m.url === model.url) ||
57+
m.name !== model.name ||
58+
m.provider !== model.provider ||
59+
m.url !== model.url,
6660
),
6761
});
6862
}
69-
function updateAvailableModels(model: string, provider: string, url?: string) {
70-
if (checkAvailableModel(model, url)) {
71-
removeModelFromAvailableModels(model, provider, url);
63+
function updateAvailableModels(model: Model) {
64+
if (checkAvailableModel(model)) {
65+
removeModelFromAvailableModels(model);
7266
} else {
73-
addModelToAvailableModels(model, provider, url);
67+
addModelToAvailableModels(model);
7468
}
7569
}
7670
77-
function checkModelAgainstEndpoint(model: string, url?: string) {
78-
if (url) {
79-
return models.value.ollama[url]?.some((m) => m === model);
71+
function checkModelAgainstEndpoint(model: Model) {
72+
if (model.url) {
73+
return models.value.ollama[model.url]?.some((m) => m.name === model.name);
8074
}
8175
return (
82-
models.value.openai.some((m) => m === model) ||
83-
models.value.gemini.some((m) => m === model) ||
84-
models.value.anthropic.some((m) => m === model)
76+
models.value.openai.some((m) => m.name === model.name) ||
77+
models.value.gemini.some((m) => m.name === model.name) ||
78+
models.value.anthropic.some((m) => m.name === model.name)
8579
);
8680
}
8781
@@ -128,7 +122,7 @@ async function testOllamaUrl(url: string) {
128122
}
129123
130124
const deleteOllamaModelModalVisible = ref(false);
131-
const ollamaModelToDelete = ref<{ name: string; url: string } | null>(null);
125+
const ollamaModelToDelete = ref<Model | null>(null);
132126
async function deleteOllamaModel() {
133127
const model = ollamaModelToDelete.value;
134128
if (!model?.url || !model.name) {
@@ -143,6 +137,8 @@ async function deleteOllamaModel() {
143137
);
144138
145139
if (response.success) {
140+
// Remove the model from the available models
141+
removeModelFromAvailableModels(model);
146142
await fetchModels("ollama", model.url);
147143
deleteOllamaModelModalVisible.value = false;
148144
}
@@ -202,7 +198,7 @@ async function pullOllamaModel(url: string) {
202198
}
203199
modelToPull.value = {};
204200
isPulling.value[url] = false;
205-
fetchModels("ollama");
201+
fetchModels("ollama", url);
206202
}
207203
208204
const openaiAvailable = ref(false);
@@ -245,17 +241,19 @@ onMounted(async () => {
245241
class="w-full grid grid-cols-2 md:grid-cols-3 gap-2 text-nowrap mb-3"
246242
>
247243
<div
248-
v-for="model in models?.openai.sort((a, b) => a.localeCompare(b))"
249-
:key="model"
244+
v-for="model in models?.openai.sort((a, b) =>
245+
a.name.localeCompare(b.name),
246+
)"
247+
:key="model.name"
250248
:class="[
251249
'flex border border-(--main-color) rounded-full px-3 cursor-pointer ',
252250
checkAvailableModel(model)
253251
? 'bg-(--main-color) text-(--bg-color)'
254252
: 'text-(--text-color)',
255253
]"
256-
@click="updateAvailableModels(model, 'openai')"
254+
@click="updateAvailableModels(model)"
257255
>
258-
<HoverScrollText>{{ model }}</HoverScrollText>
256+
<HoverScrollText>{{ model.displayName }}</HoverScrollText>
259257
</div>
260258
</div>
261259
</SettingsGroup>
@@ -270,17 +268,19 @@ onMounted(async () => {
270268
class="w-full grid grid-cols-2 md:grid-cols-3 gap-2 text-nowrap mb-3"
271269
>
272270
<div
273-
v-for="model in models?.gemini.sort((a, b) => a.localeCompare(b))"
274-
:key="model"
271+
v-for="model in models?.gemini.sort((a, b) =>
272+
a.name.localeCompare(b.name),
273+
)"
274+
:key="model.name"
275275
:class="[
276276
'flex border border-(--main-color) rounded-full px-3 cursor-pointer ',
277277
checkAvailableModel(model)
278278
? 'bg-(--main-color) text-(--bg-color)'
279279
: 'text-(--text-color)',
280280
]"
281-
@click="updateAvailableModels(model, 'gemini')"
281+
@click="updateAvailableModels(model)"
282282
>
283-
<HoverScrollText>{{ model }}</HoverScrollText>
283+
<HoverScrollText>{{ model.displayName }}</HoverScrollText>
284284
</div>
285285
</div>
286286
</SettingsGroup>
@@ -295,17 +295,19 @@ onMounted(async () => {
295295
class="w-full grid grid-cols-2 md:grid-cols-3 gap-2 text-nowrap mb-3"
296296
>
297297
<div
298-
v-for="model in models?.anthropic.sort((a, b) => a.localeCompare(b))"
299-
:key="model"
298+
v-for="model in models?.anthropic.sort((a, b) =>
299+
a.name.localeCompare(b.name),
300+
)"
301+
:key="model.name"
300302
:class="[
301303
'flex border border-(--main-color) rounded-full px-3 cursor-pointer ',
302304
checkAvailableModel(model)
303305
? 'bg-(--main-color) text-(--bg-color)'
304306
: 'text-(--text-color)',
305307
]"
306-
@click="updateAvailableModels(model, 'anthropic')"
308+
@click="updateAvailableModels(model)"
307309
>
308-
<HoverScrollText>{{ model }}</HoverScrollText>
310+
<HoverScrollText>{{ model.displayName }}</HoverScrollText>
309311
</div>
310312
</div>
311313
</SettingsGroup>
@@ -394,24 +396,24 @@ onMounted(async () => {
394396
>
395397
<div
396398
v-for="model in (models?.ollama[url] || []).sort((a, b) =>
397-
a.localeCompare(b),
399+
a.name.localeCompare(b.name),
398400
)"
399-
:key="model"
401+
:key="model.name"
400402
:class="[
401403
'flex items-center justify-between gap-2 border border-(--main-color) rounded-full text-center truncate px-3 cursor-pointer',
402-
checkAvailableModel(model, url)
404+
checkAvailableModel(model)
403405
? 'bg-(--main-color) text-(--bg-color)'
404406
: 'text-(--text-color)',
405407
]"
406-
@click="updateAvailableModels(model, 'ollama', url)"
408+
@click="updateAvailableModels(model)"
407409
>
408-
<HoverScrollText>{{ model }}</HoverScrollText>
410+
<HoverScrollText>{{ model.displayName }}</HoverScrollText>
409411
<Icon
410412
name="lucide:trash-2"
411413
class="text-(--text-color) ml-1"
412414
@click.stop.prevent="
413415
() => {
414-
ollamaModelToDelete = { name: model, url };
416+
ollamaModelToDelete = model;
415417
deleteOllamaModelModalVisible = true;
416418
}
417419
"
@@ -421,17 +423,14 @@ onMounted(async () => {
421423
</div>
422424
</SettingsGroup>
423425
<SettingsGroup
424-
v-if="
425-
availableModels.filter((m) => !checkModelAgainstEndpoint(m.name, m.url))
426-
.length
427-
"
426+
v-if="availableModels.filter((m) => !checkModelAgainstEndpoint(m)).length"
428427
title="leftover models"
429428
icon="lucide:alert-triangle"
430429
description="these models are currently not available via an api endpoint, but are still present in the system."
431430
>
432431
<div
433432
v-for="model in availableModels.filter(
434-
(m) => !checkModelAgainstEndpoint(m.name, m.url),
433+
(m) => !checkModelAgainstEndpoint(m),
435434
)"
436435
:key="model.name"
437436
class="flex items-center gap-2 mb-4"
@@ -443,11 +442,7 @@ onMounted(async () => {
443442
class="bg-(--bg-color) text-(--error-color) rounded px-1! py-1! cursor-pointer"
444443
@click.prevent.stop="
445444
() => {
446-
removeModelFromAvailableModels(
447-
model.name,
448-
model.provider,
449-
model.url,
450-
);
445+
removeModelFromAvailableModels(model);
451446
}
452447
"
453448
>

app/utils/db/local.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { triggerDebouncedSync } from "../sync/debounce";
77
//------------------------//
88
export interface Model {
99
name: string;
10+
displayName: string;
1011
provider: string;
1112
url?: string;
1213
}

server/api/models/anthropic/index.get.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ export default defineEventHandler(async (event) => {
2222

2323
try {
2424
const modelsList = await anthropic.models.list();
25-
const models = modelsList.data.map((m) => m.id);
25+
const models = modelsList.data.map((m) => ({
26+
name: m.id,
27+
displayName: m.display_name,
28+
provider: "anthropic",
29+
}));
2630

2731
return {
2832
models,

server/api/models/gemini/index.get.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ export default defineEventHandler(async (event) => {
3131
);
3232
const models = response.models
3333
.filter((m) => m.name?.startsWith("models/gemini"))
34-
.map((m) => m.name?.slice("models/".length));
34+
.map((m) => ({
35+
name: m.name?.slice("models/".length),
36+
displayName: m.displayName,
37+
provider: "gemini",
38+
}));
3539

3640
return {
3741
models,

server/api/models/ollama/index.get.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,17 @@ export default defineEventHandler(async (event) => {
4848
"GET /api/models/ollama: Error fetching Ollama models from the provided URL",
4949
);
5050
}
51+
const models = ollamaModels.models.length
52+
? ollamaModels.models.map((model: OllamaModel) => ({
53+
name: model.name,
54+
displayName: model.name,
55+
provider: "ollama",
56+
url,
57+
}))
58+
: [];
5159

5260
return {
53-
models: ollamaModels.models.length
54-
? ollamaModels.models.map((model: OllamaModel) => model.name)
55-
: [],
61+
models,
5662
};
5763
} catch (error) {
5864
logger.error(error, "GET /api/models/ollama: Error fetching models");

0 commit comments

Comments
 (0)