Skip to content

Commit 3d6bd65

Browse files
authored
Merge pull request #215 from Routstr/v0.2.0-final
* fix model filtering * cleanup desing
2 parents 64bf8ae + 8c08be9 commit 3d6bd65

File tree

14 files changed

+149
-104
lines changed

14 files changed

+149
-104
lines changed

routstr/payment/models.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,6 @@ async def _cleanup_enabled_models_once() -> None:
577577

578578
for db_model in db_models:
579579
# Find corresponding upstream model
580-
print(db_model.id)
581580
upstream_model = None
582581
for upstream in upstreams:
583582
upstream_model = upstream.get_cached_model_by_id(db_model.id)
@@ -613,7 +612,7 @@ async def _cleanup_enabled_models_once() -> None:
613612

614613

615614
def _pricing_matches(
616-
db_pricing: dict, upstream_pricing: dict, tolerance: float = 0.1
615+
db_pricing: dict, upstream_pricing: dict, tolerance: float = 0.0
617616
) -> bool:
618617
"""Check if pricing dictionaries match within tolerance."""
619618
keys_to_compare = [
@@ -626,9 +625,8 @@ def _pricing_matches(
626625
]
627626

628627
for key in keys_to_compare:
629-
db_val = float(db_pricing.get(key, 0.0)) * 1000000
630-
upstream_val = float(upstream_pricing.get(key, 0.0)) * 1000000
631-
print(db_val - upstream_val)
628+
db_val = int(float(db_pricing.get(key, 0.0)) * 1000000)
629+
upstream_val = int(float(upstream_pricing.get(key, 0.0)) * 1000000)
632630

633631
if abs(db_val - upstream_val) > tolerance:
634632
return False

routstr/proxy.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from fastapi import APIRouter, Depends, HTTPException, Request
55
from fastapi.responses import Response, StreamingResponse
6-
from sqlmodel import col, select
6+
from sqlmodel import select
77

88
from .algorithm import create_model_mappings
99
from .auth import pay_for_request, revert_pay_for_request, validate_bearer_key
@@ -83,9 +83,7 @@ async def refresh_model_maps() -> None:
8383

8484
# Gather database overrides and disabled models
8585
async with create_session() as session:
86-
result = await session.exec(
87-
select(ModelRow).where(col(ModelRow.enabled).is_(True))
88-
)
86+
result = await session.exec(select(ModelRow).where(ModelRow.enabled))
8987
override_rows = result.all()
9088

9189
provider_result = await session.exec(select(UpstreamProviderRow))
@@ -103,7 +101,7 @@ async def refresh_model_maps() -> None:
103101
}
104102

105103
disabled_result = await session.exec(
106-
select(ModelRow.id).where(col(ModelRow.enabled).is_(False))
104+
select(ModelRow.id).where(ModelRow.enabled == False) # noqa: E712
107105
)
108106
disabled_model_ids = {row for row in disabled_result.all()}
109107

routstr/upstreams/ollama.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ async def fetch_models(self) -> list[Model]:
121121
models_list.append(
122122
Model(
123123
id=model_name,
124-
name=model_name,
124+
name=model_name.replace(":", " "),
125125
created=0,
126126
description=description,
127127
context_length=context_length,

scripts/build-ui.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ else
4949
npm run build
5050
fi
5151

52+
rm -rf ../ui_out
5253
mkdir -p ../ui_out
5354
mv out/* ../ui_out
5455

ui/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default function RootLayout({
3434
return (
3535
<html lang='en' suppressHydrationWarning>
3636
<body
37-
className={`${geistSans.variable} ${geistMono.variable} antialiased font-sans`}
37+
className={`${geistSans.variable} ${geistMono.variable} font-sans antialiased`}
3838
>
3939
<SuppressHydrationWarning>
4040
<Providers>{children}</Providers>

ui/app/model/page.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
1616
import { Badge } from '@/components/ui/badge';
1717
import { useMemo, useState } from 'react';
1818
import type { Model } from '@/lib/api/schemas/models';
19+
import { groupAndSortModelsByProvider } from '@/lib/utils/modelSort';
1920

2021
export default function ModelsPage() {
2122
const [filteredModels, setFilteredModels] = useState<Model[]>([]);
@@ -34,15 +35,7 @@ export default function ModelsPage() {
3435

3536
const groupedModels = useMemo(() => {
3637
if (!models) return {};
37-
38-
return models.reduce<Record<string, typeof models>>((acc, model) => {
39-
const provider = model.provider;
40-
if (!acc[provider]) {
41-
acc[provider] = [];
42-
}
43-
acc[provider].push(model);
44-
return acc;
45-
}, {});
38+
return groupAndSortModelsByProvider(models);
4639
}, [models]);
4740

4841
const groupDataMap = useMemo(() => {
@@ -52,7 +45,9 @@ export default function ModelsPage() {
5245
const providerInfo = useMemo(() => {
5346
return Object.entries(groupedModels).map(([provider, providerModels]) => {
5447
const groupData = groupDataMap.get(provider);
55-
const activeModels = providerModels.filter((m) => !m.soft_deleted).length;
48+
const activeModels = providerModels.filter(
49+
(m) => m.isEnabled && !m.soft_deleted
50+
).length;
5651
const totalModels = providerModels.length;
5752

5853
return {
@@ -156,7 +151,10 @@ export default function ModelsPage() {
156151
models={models}
157152
onFilteredModelsChange={setFilteredModels}
158153
/>
159-
<ModelSelector filteredModels={filteredModels} />
154+
<ModelSelector
155+
filteredModels={filteredModels}
156+
showDeleteAllButton={true}
157+
/>
160158
</div>
161159
</TabsContent>
162160

@@ -183,7 +181,7 @@ export default function ModelsPage() {
183181
(m) => m.soft_deleted
184182
).length
185183
}{' '}
186-
soft deleted
184+
disabled
187185
</span>
188186
)}
189187
{groupData?.group_url && (
@@ -199,6 +197,7 @@ export default function ModelsPage() {
199197
filterProvider={provider}
200198
groupData={groupData}
201199
showProviderActions={true}
200+
showDeleteAllButton={false}
202201
/>
203202
</div>
204203
</TabsContent>

ui/app/providers/page.tsx

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,11 @@ export default function ProvidersPage() {
277277
}
278278
placeholder='https://api.example.com/v1'
279279
disabled={hasFixedBaseUrl(formData.provider_type)}
280-
className={hasFixedBaseUrl(formData.provider_type) ? 'cursor-not-allowed opacity-60' : ''}
280+
className={
281+
hasFixedBaseUrl(formData.provider_type)
282+
? 'cursor-not-allowed opacity-60'
283+
: ''
284+
}
281285
/>
282286
</div>
283287
<div className='grid gap-2'>
@@ -453,7 +457,8 @@ export default function ProvidersPage() {
453457
<div className='space-y-2'>
454458
{providerModels.db_models.length === 0 ? (
455459
<div className='text-muted-foreground py-4 text-center text-sm'>
456-
No models configured. Add custom models to use this provider.
460+
No models configured. Add custom models to
461+
use this provider.
457462
</div>
458463
) : (
459464
<div className='space-y-2'>
@@ -495,7 +500,10 @@ export default function ProvidersPage() {
495500
</div>
496501
) : (
497502
// Has provided models - show tabs
498-
<Tabs defaultValue='provided' className='w-full'>
503+
<Tabs
504+
defaultValue='provided'
505+
className='w-full'
506+
>
499507
<TabsList className='grid w-full grid-cols-2'>
500508
<TabsTrigger
501509
value='provided'
@@ -504,7 +512,9 @@ export default function ProvidersPage() {
504512
<span className='hidden sm:inline'>
505513
Provided Models
506514
</span>
507-
<span className='sm:hidden'>Provided</span>
515+
<span className='sm:hidden'>
516+
Provided
517+
</span>
508518
<Badge
509519
variant='secondary'
510520
className='ml-1 text-xs sm:ml-2'
@@ -534,7 +544,8 @@ export default function ProvidersPage() {
534544
>
535545
{providerModels.db_models.length > 0 && (
536546
<div className='text-muted-foreground mb-3 text-sm'>
537-
Custom models override or extend the provider&apos;s catalog.
547+
Custom models override or extend the
548+
provider&apos;s catalog.
538549
</div>
539550
)}
540551
{providerModels.db_models.length === 0 ? (
@@ -543,49 +554,54 @@ export default function ProvidersPage() {
543554
</div>
544555
) : (
545556
<div className='space-y-2'>
546-
{providerModels.db_models.map((model) => (
547-
<div
548-
key={model.id}
549-
className='hover:bg-accent flex flex-col gap-2 rounded-lg border p-3 transition-colors sm:flex-row sm:items-center sm:justify-between'
550-
>
551-
<div className='min-w-0 flex-1'>
552-
<div className='flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-2'>
553-
<span className='truncate font-mono text-sm font-medium'>
554-
{model.id}
555-
</span>
556-
<Badge
557-
variant={
558-
model.enabled
559-
? 'default'
560-
: 'secondary'
561-
}
562-
className='w-fit text-xs'
563-
>
564-
{model.enabled
565-
? 'Enabled'
566-
: 'Disabled'}
567-
</Badge>
557+
{providerModels.db_models.map(
558+
(model) => (
559+
<div
560+
key={model.id}
561+
className='hover:bg-accent flex flex-col gap-2 rounded-lg border p-3 transition-colors sm:flex-row sm:items-center sm:justify-between'
562+
>
563+
<div className='min-w-0 flex-1'>
564+
<div className='flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-2'>
565+
<span className='truncate font-mono text-sm font-medium'>
566+
{model.id}
567+
</span>
568+
<Badge
569+
variant={
570+
model.enabled
571+
? 'default'
572+
: 'secondary'
573+
}
574+
className='w-fit text-xs'
575+
>
576+
{model.enabled
577+
? 'Enabled'
578+
: 'Disabled'}
579+
</Badge>
580+
</div>
581+
<div className='text-muted-foreground mt-1 text-xs break-words'>
582+
{model.description ||
583+
model.name}
584+
</div>
568585
</div>
569-
<div className='text-muted-foreground mt-1 text-xs break-words'>
570-
{model.description || model.name}
586+
<div className='text-muted-foreground text-xs whitespace-nowrap'>
587+
{model.context_length?.toLocaleString()}{' '}
588+
tokens
571589
</div>
572590
</div>
573-
<div className='text-muted-foreground text-xs whitespace-nowrap'>
574-
{model.context_length?.toLocaleString()}{' '}
575-
tokens
576-
</div>
577-
</div>
578-
))}
591+
)
592+
)}
579593
</div>
580594
)}
581595
</TabsContent>
582596
<TabsContent
583597
value='provided'
584598
className='mt-4 space-y-2'
585599
>
586-
{providerModels.remote_models.length > 0 && (
600+
{providerModels.remote_models.length >
601+
0 && (
587602
<div className='text-muted-foreground mb-3 text-sm'>
588-
Models automatically discovered from the provider&apos;s catalog.
603+
Models automatically discovered from the
604+
provider&apos;s catalog.
589605
</div>
590606
)}
591607
<div className='space-y-2'>
@@ -670,7 +686,11 @@ export default function ProvidersPage() {
670686
}
671687
placeholder='https://api.example.com/v1'
672688
disabled={hasFixedBaseUrl(formData.provider_type)}
673-
className={hasFixedBaseUrl(formData.provider_type) ? 'cursor-not-allowed opacity-60' : ''}
689+
className={
690+
hasFixedBaseUrl(formData.provider_type)
691+
? 'cursor-not-allowed opacity-60'
692+
: ''
693+
}
674694
/>
675695
</div>
676696
<div className='grid gap-2'>

0 commit comments

Comments
 (0)