Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions backend/src/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -947,11 +947,14 @@ export async function getModelsWithProviderBySystemName(

/**
* list unique system names (for global model registry)
* Returns active model names and archived names (deleted but referenced by historical requests)
*/
export async function listUniqueSystemNames(
modelType?: ModelTypeEnumType,
): Promise<string[]> {
): Promise<{ active: string[]; archived: string[] }> {
logger.debug("listUniqueSystemNames", modelType);

// Get active model names (non-deleted models with non-deleted providers)
const r = await db
.selectDistinct({ systemName: schema.ModelsTable.systemName })
.from(schema.ModelsTable)
Expand All @@ -967,7 +970,28 @@ export async function listUniqueSystemNames(
),
)
.orderBy(asc(schema.ModelsTable.systemName));
return r.map((x) => x.systemName);
const active = r.map((x) => x.systemName);

// Get archived model names: exist in completions/embeddings but not in active models
const archivedResult = await db.execute(sql`
SELECT DISTINCT model AS name FROM (
SELECT DISTINCT model FROM completions WHERE deleted = false
UNION
SELECT DISTINCT model FROM embeddings WHERE deleted = false
) AS all_models
WHERE model NOT IN (
SELECT DISTINCT m.system_name
FROM models m
INNER JOIN providers p ON m.provider_id = p.id
WHERE m.deleted = false AND p.deleted = false
)
ORDER BY name ASC
`);
const archived = (archivedResult as unknown as { name: string }[]).map(
(x) => x.name,
);

return { active, archived };
Comment thread
pescn marked this conversation as resolved.
}

/**
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@
"pages.models.registry.WeightConfiguration": "Weight Configuration",
"pages.models.registry.History": "History",
"pages.models.registry.ViewHistory": "View request history",
"pages.models.registry.Archived": "Archived",
"pages.models.registry.ArchivedTooltip": "This model has been deleted but has historical requests",
"routes.models.Title": "Models",
"routes.models.Description": "Configure model providers and global models.",
"routes.models.nav.Providers": "Model Providers",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@
"pages.models.registry.WeightConfiguration": "权重配置",
"pages.models.registry.History": "历史",
"pages.models.registry.ViewHistory": "查看请求历史",
"pages.models.registry.Archived": "已归档",
"pages.models.registry.ArchivedTooltip": "该模型已删除但存在历史请求记录",
"routes.models.Title": "模型",
"routes.models.Description": "配置模型供应商和全局模型。",
"routes.models.nav.Providers": "模型供应商",
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/models/models-registry-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,15 @@ function ModelsBySystemNameTable({ systemName }: { systemName: string }) {
const { data: models = [], isLoading } = useQuery({
queryKey: ['models', 'by-system-name', systemName],
queryFn: async () => {
const { data, error } = await api.admin.models['by-system-name'][systemName].get()
const { data, error } = await api.admin.models['by-system-name'][encodeURIComponent(systemName)].get()
if (error) throw error
return data as ModelWithProvider[]
},
})

const updateWeightsMutation = useMutation({
mutationFn: async (weights: { modelId: number; weight: number }[]) => {
const { error } = await api.admin.models['by-system-name'][systemName].weights.put({
const { error } = await api.admin.models['by-system-name'][encodeURIComponent(systemName)].weights.put({
weights,
})
if (error) throw error
Expand Down
61 changes: 55 additions & 6 deletions frontend/src/pages/settings/models-settings-page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { CpuIcon, HistoryIcon } from 'lucide-react'
import { ArchiveIcon, CpuIcon, HistoryIcon } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'

Expand All @@ -25,8 +25,14 @@ interface ModelWithProvider {
}
}

export function ModelsSettingsPage({ systemNames }: { systemNames: string[] }) {
interface ModelsSettingsPageProps {
activeSystemNames: string[]
archivedSystemNames: string[]
}

export function ModelsSettingsPage({ activeSystemNames, archivedSystemNames }: ModelsSettingsPageProps) {
const { t } = useTranslation()
const hasAny = activeSystemNames.length > 0 || archivedSystemNames.length > 0

return (
<div className="space-y-8">
Expand All @@ -36,7 +42,7 @@ export function ModelsSettingsPage({ systemNames }: { systemNames: string[] }) {
<CardDescription className="text-sm">{t('pages.models.registry.Description')}</CardDescription>
</CardHeader>
<CardContent>
{systemNames.length > 0 ? (
{hasAny ? (
<Table>
<TableHeader>
<TableRow>
Expand All @@ -47,9 +53,12 @@ export function ModelsSettingsPage({ systemNames }: { systemNames: string[] }) {
</TableRow>
</TableHeader>
<TableBody>
{systemNames.map((systemName) => (
{activeSystemNames.map((systemName) => (
<ModelRow key={systemName} systemName={systemName} />
))}
{archivedSystemNames.map((systemName) => (
<ArchivedModelRow key={systemName} systemName={systemName} />
))}
</TableBody>
</Table>
) : (
Expand All @@ -69,7 +78,7 @@ function ModelRow({ systemName }: { systemName: string }) {
const { data: models = [], isLoading } = useQuery({
queryKey: ['models', 'by-system-name', systemName],
queryFn: async () => {
const { data, error } = await api.admin.models['by-system-name'][systemName].get()
const { data, error } = await api.admin.models['by-system-name'][encodeURIComponent(systemName)].get()
if (error) throw error
return data as ModelWithProvider[]
},
Expand Down Expand Up @@ -157,6 +166,46 @@ function ModelRow({ systemName }: { systemName: string }) {
)
}

function ArchivedModelRow({ systemName }: { systemName: string }) {
const { t } = useTranslation()
const navigate = useNavigate()

const handleHistoryClick = (e: React.MouseEvent) => {
e.stopPropagation()
navigate({ to: '/requests', search: { model: systemName } })
Comment thread
pescn marked this conversation as resolved.
Outdated
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

return (
<TableRow className="opacity-50">
<TableCell>
<div className="flex items-center gap-3">
<ArchiveIcon className="text-muted-foreground/50 size-5" />
<span className="text-muted-foreground font-mono text-sm font-medium line-through">{systemName}</span>
</div>
</TableCell>
<TableCell>
<span className="text-muted-foreground text-sm">-</span>
</TableCell>
<TableCell>
<span className="text-muted-foreground text-sm italic" title={t('pages.models.registry.ArchivedTooltip')}>
{t('pages.models.registry.Archived')}
</span>
</TableCell>
<TableCell className="text-center">
<Button
variant="ghost"
size="sm"
className="size-8 p-0"
onClick={handleHistoryClick}
title={t('pages.models.registry.ViewHistory')}
>
<HistoryIcon className="size-4" />
</Button>
</TableCell>
</TableRow>
)
}

interface LoadBalancingDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
Expand All @@ -182,7 +231,7 @@ function LoadBalancingDialog({ open, onOpenChange, systemName, models }: LoadBal

const updateWeightsMutation = useMutation({
mutationFn: async (weights: { modelId: number; weight: number }[]) => {
const { error } = await api.admin.models['by-system-name'][systemName].weights.put({
const { error } = await api.admin.models['by-system-name'][encodeURIComponent(systemName)].weights.put({
weights,
})
if (error) throw error
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/models/registry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ export const Route = createFileRoute('/models/registry')({
function RouteComponent() {
const { data } = useSuspenseQuery(systemNamesQueryOptions())

return <ModelsSettingsPage systemNames={data} />
return <ModelsSettingsPage activeSystemNames={data.active} archivedSystemNames={data.archived} />
}