Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const BILLING_SECTIONS = [
modelDefaults={getModelDefaults(settings)}
groupDefaults={getGroupDefaults(settings)}
toolPricesDefault={settings['tool_price_setting.prices']}
visibleTabs={['models', 'tool-prices', 'upstream-sync']}
visibleTabs={['models', 'unset-models', 'tool-prices', 'upstream-sync']}
/>
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export type ModelRow = ModelPricingSnapshot & {
export const hasPricingValue = (value?: string) =>
value !== undefined && value !== ''

export const isBasePricingUnset = (snapshot?: ModelPricingSnapshot) =>
!snapshot ||
(snapshot.billingMode !== 'tiered_expr' &&
!hasPricingValue(snapshot.price) &&
!hasPricingValue(snapshot.ratio))

const toNumberOrNull = (value?: string) => {
if (!hasPricingValue(value)) return null
const num = Number(value)
Expand Down
123 changes: 71 additions & 52 deletions web/default/src/features/system-settings/models/model-ratio-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.

For commercial licensing, please contact support@quantumnous.com
*/
import { useQuery } from '@tanstack/react-query'
import { Code2, Eye, RotateCcw, Save } from 'lucide-react'
import { memo, useCallback, useRef, useState } from 'react'
import { type UseFormReturn } from 'react-hook-form'
Expand All @@ -33,6 +34,7 @@ import {
FormMessage,
} from '@/components/ui/form'
import { Switch } from '@/components/ui/switch'
import { getEnabledModels } from '@/features/channels/api'

import {
SettingsForm,
Expand Down Expand Up @@ -65,6 +67,7 @@ type ModelRatioFormProps = {
onReset: () => void
isSaving: boolean
isResetting: boolean
variant?: 'default' | 'unset'
}

type ModelJsonFieldName =
Expand Down Expand Up @@ -164,11 +167,19 @@ export const ModelRatioForm = memo(function ModelRatioForm({
onReset,
isSaving,
isResetting,
variant = 'default',
}: ModelRatioFormProps) {
const { t } = useTranslation()
const isUnsetVariant = variant === 'unset'
const [editMode, setEditMode] = useState<'visual' | 'json'>('visual')
const visualEditorRef = useRef<ModelRatioVisualEditorHandle>(null)

const enabledModelsQuery = useQuery({
queryKey: ['enabled-models'],
queryFn: getEnabledModels,
enabled: isUnsetVariant,
})

const handleFieldChange = useCallback(
(field: keyof ModelFormValues, value: string) => {
form.setValue(field, value, {
Expand All @@ -194,42 +205,44 @@ export const ModelRatioForm = memo(function ModelRatioForm({

return (
<div className='space-y-6'>
<div className='flex flex-wrap justify-end gap-2'>
<Button
type='button'
variant='destructive'
size='sm'
onClick={onReset}
disabled={isResetting}
>
<RotateCcw data-icon='inline-start' />
{t('Reset prices')}
</Button>
{editMode === 'json' && (
{!isUnsetVariant && (
<div className='flex flex-wrap justify-end gap-2'>
<Button
type='button'
variant='destructive'
size='sm'
onClick={handleSave}
disabled={isSaving}
onClick={onReset}
disabled={isResetting}
>
<Save data-icon='inline-start' />
{isSaving ? t('Saving...') : t('Save model prices')}
<RotateCcw data-icon='inline-start' />
{t('Reset prices')}
</Button>
)}
<Button variant='outline' size='sm' onClick={toggleEditMode}>
{editMode === 'visual' ? (
<>
<Code2 className='mr-2 h-4 w-4' />
{t('Switch to JSON')}
</>
) : (
<>
<Eye className='mr-2 h-4 w-4' />
{t('Switch to Visual')}
</>
{editMode === 'json' && (
<Button
type='button'
size='sm'
onClick={handleSave}
disabled={isSaving}
>
<Save data-icon='inline-start' />
{isSaving ? t('Saving...') : t('Save model prices')}
</Button>
)}
</Button>
</div>
<Button variant='outline' size='sm' onClick={toggleEditMode}>
{editMode === 'visual' ? (
<>
<Code2 className='mr-2 h-4 w-4' />
{t('Switch to JSON')}
</>
) : (
<>
<Eye className='mr-2 h-4 w-4' />
{t('Switch to Visual')}
</>
)}
</Button>
</div>
)}

<Form {...form}>
{editMode === 'visual' ? (
Expand All @@ -256,6 +269,10 @@ export const ModelRatioForm = memo(function ModelRatioForm({
audioCompletionRatio={form.watch('AudioCompletionRatio')}
billingMode={form.watch('BillingMode')}
billingExpr={form.watch('BillingExpr')}
candidateModelNames={
isUnsetVariant ? enabledModelsQuery.data?.data : undefined
}
filterMode={isUnsetVariant ? 'unset' : 'all'}
onSave={handleSave}
isSaving={isSaving}
onChange={(field, value) => {
Expand All @@ -269,28 +286,30 @@ export const ModelRatioForm = memo(function ModelRatioForm({
}}
/>

<FormField
control={form.control}
name='ExposeRatioEnabled'
render={({ field }) => (
<SettingsSwitchItem>
<SettingsSwitchContent>
<FormLabel>{t('Expose ratio API')}</FormLabel>
<FormDescription>
{t(
'Allow clients to query configured ratios via `/api/ratio`.'
)}
</FormDescription>
</SettingsSwitchContent>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</SettingsSwitchItem>
)}
/>
{!isUnsetVariant && (
<FormField
control={form.control}
name='ExposeRatioEnabled'
render={({ field }) => (
<SettingsSwitchItem>
<SettingsSwitchContent>
<FormLabel>{t('Expose ratio API')}</FormLabel>
<FormDescription>
{t(
'Allow clients to query configured ratios via `/api/ratio`.'
)}
</FormDescription>
</SettingsSwitchContent>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</SettingsSwitchItem>
)}
/>
)}
</div>
) : (
<SettingsForm onSubmit={form.handleSubmit(onSave)}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ const filterBySelectedValues = (
type BuildModelRatioColumnsOptions = {
onDelete: (name: string) => void
onEdit: (model: ModelRow) => void
deleteDisabled?: boolean
t: (key: string) => string
}

export function buildModelRatioColumns({
onDelete,
onEdit,
deleteDisabled,
t,
}: BuildModelRatioColumnsOptions): ColumnDef<ModelRow>[] {
return [
Expand Down Expand Up @@ -151,6 +153,7 @@ export function buildModelRatioColumns({
menuLabel={t('Open menu')}
onEdit={() => onEdit(row.original)}
onDelete={() => onDelete(row.original.name)}
deleteDisabled={deleteDisabled}
/>
),
enableHiding: false,
Expand Down
Loading