From b188800f1663d11ff2227998dcab04d43787830a Mon Sep 17 00:00:00 2001 From: JzoNg Date: Tue, 12 Nov 2024 16:40:43 +0800 Subject: [PATCH] model selector in endpoint modal --- .../model-provider-page/declarations.ts | 31 ++++--- .../model-provider-page/model-modal/Form.tsx | 85 +++++++++++++++++-- .../model-provider-page/model-modal/Input.tsx | 10 +-- 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/web/app/components/header/account-setting/model-provider-page/declarations.ts b/web/app/components/header/account-setting/model-provider-page/declarations.ts index c50a17c6b2..f1b1f8741a 100644 --- a/web/app/components/header/account-setting/model-provider-page/declarations.ts +++ b/web/app/components/header/account-setting/model-provider-page/declarations.ts @@ -1,6 +1,6 @@ export type FormValue = Record -export interface TypeWithI18N { +export type TypeWithI18N = { en_US: T zh_Hans: T [key: string]: T @@ -15,9 +15,12 @@ export enum FormTypeEnum { boolean = 'boolean', files = 'files', file = 'file', + modelSelector = 'model-selector', + toolSelector = 'tool-selector', + appSelector = 'app-selector', } -export interface FormOption { +export type FormOption = { label: TypeWithI18N value: string show_on: FormShowOnObject[] @@ -89,12 +92,12 @@ export enum CustomConfigurationStatusEnum { noConfigure = 'no-configure', } -export interface FormShowOnObject { +export type FormShowOnObject = { variable: string value: string } -export interface CredentialFormSchemaBase { +export type CredentialFormSchemaBase = { variable: string label: TypeWithI18N type: FormTypeEnum @@ -112,7 +115,7 @@ export type CredentialFormSchemaRadio = CredentialFormSchemaBase & { options: Fo export type CredentialFormSchemaSecretInput = CredentialFormSchemaBase & { placeholder?: TypeWithI18N } export type CredentialFormSchema = CredentialFormSchemaTextInput | CredentialFormSchemaSelect | CredentialFormSchemaRadio | CredentialFormSchemaSecretInput -export interface ModelItem { +export type ModelItem = { model: string label: TypeWithI18N model_type: ModelTypeEnum @@ -141,7 +144,7 @@ export enum QuotaUnitEnum { credits = 'credits', } -export interface QuotaConfiguration { +export type QuotaConfiguration = { quota_type: CurrentSystemQuotaTypeEnum quota_unit: QuotaUnitEnum quota_limit: number @@ -150,7 +153,7 @@ export interface QuotaConfiguration { is_valid: boolean } -export interface ModelProvider { +export type ModelProvider = { provider: string label: TypeWithI18N description?: TypeWithI18N @@ -184,7 +187,7 @@ export interface ModelProvider { } } -export interface Model { +export type Model = { provider: string icon_large: TypeWithI18N icon_small: TypeWithI18N @@ -193,7 +196,7 @@ export interface Model { status: ModelStatusEnum } -export interface DefaultModelResponse { +export type DefaultModelResponse = { model: string model_type: ModelTypeEnum provider: { @@ -203,17 +206,17 @@ export interface DefaultModelResponse { } } -export interface DefaultModel { +export type DefaultModel = { provider: string model: string } -export interface CustomConfigurationModelFixedFields { +export type CustomConfigurationModelFixedFields = { __model_name: string __model_type: ModelTypeEnum } -export interface ModelParameterRule { +export type ModelParameterRule = { default?: number | string | boolean | string[] help?: TypeWithI18N label: TypeWithI18N @@ -228,7 +231,7 @@ export interface ModelParameterRule { tagPlaceholder?: TypeWithI18N } -export interface ModelLoadBalancingConfigEntry { +export type ModelLoadBalancingConfigEntry = { /** model balancing config entry id */ id?: string /** is config entry enabled */ @@ -243,7 +246,7 @@ export interface ModelLoadBalancingConfigEntry { ttl?: number } -export interface ModelLoadBalancingConfig { +export type ModelLoadBalancingConfig = { enabled: boolean configs: ModelLoadBalancingConfigEntry[] } diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx index c0a7be68a6..90d0688db0 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useCallback, useState } from 'react' import type { FC } from 'react' import { ValidatingTip } from '../../key-validator/ValidateStatus' import type { @@ -17,6 +17,8 @@ import cn from '@/utils/classnames' import { SimpleSelect } from '@/app/components/base/select' import Tooltip from '@/app/components/base/tooltip' import Radio from '@/app/components/base/radio' +import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal' + type FormProps = { className?: string itemClassName?: string @@ -67,6 +69,24 @@ const Form: FC = ({ onChange({ ...value, [key]: val, ...shouldClearVariable }) } + const handleModelChanged = useCallback((key: string, model: { provider: string; modelId: string; mode?: string }) => { + const newValue = { + ...value[key], + provider: model.provider, + name: model.modelId, + mode: model.mode, + } + onChange({ ...value, [key]: newValue }) + }, [onChange, value]) + + const handleCompletionParamsChange = useCallback((key: string, newParams: Record) => { + const newValue = { + ...value[key], + completion_params: newParams, + } + onChange({ ...value, [key]: newValue }) + }, [onChange, value]) + const renderField = (formSchema: CredentialFormSchema) => { const tooltip = formSchema.tooltip const tooltipContent = (tooltip && ( @@ -94,7 +114,7 @@ const Form: FC = ({ const disabled = readonly || (isEditMode && (variable === '__model_type' || variable === '__model_name')) return (
-
+
{label[language] || label.en_US} { required && ( @@ -135,7 +155,7 @@ const Form: FC = ({ return (
-
+
{label[language] || label.en_US} { required && ( @@ -165,7 +185,7 @@ const Form: FC = ({ flex justify-center items-center mr-2 w-4 h-4 border border-gray-300 rounded-full ${value[variable] === option.value && 'border-[5px] border-primary-600'} `} /> -
{option.label[language] || option.label.en_US}
+
{option.label[language] || option.label.en_US}
)) } @@ -176,7 +196,7 @@ const Form: FC = ({ ) } - if (formSchema.type === 'select') { + if (formSchema.type === FormTypeEnum.select) { const { options, variable, @@ -191,7 +211,7 @@ const Form: FC = ({ return (
-
+
{label[language] || label.en_US} { @@ -202,6 +222,7 @@ const Form: FC = ({ {tooltipContent}
= ({ ) } - if (formSchema.type === 'boolean') { + if (formSchema.type === FormTypeEnum.boolean) { const { variable, label, @@ -233,9 +254,9 @@ const Form: FC = ({ return (
-
+
- {label[language] || label.en_US} + {label[language] || label.en_US} { required && ( * @@ -256,6 +277,52 @@ const Form: FC = ({
) } + + if (formSchema.type === FormTypeEnum.modelSelector) { + const { + variable, + label, + required, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + + return ( +
+
+ {label[language] || label.en_US} + { + required && ( + * + ) + } + {tooltipContent} +
+ handleModelChanged(variable, model)} + onCompletionParamsChange={params => handleCompletionParamsChange(variable, params)} + hideDebugWithMultipleModel + debugWithMultipleModel={false} + readonly={readonly} + /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && } +
+ ) + } + + if (formSchema.type === FormTypeEnum.toolSelector) { + // TODO + } + + if (formSchema.type === FormTypeEnum.appSelector) { + // TODO + } } return ( diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx index 86d52619e6..ee9d75becc 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx @@ -26,14 +26,14 @@ const Input: FC = ({ max, }) => { const toLimit = (v: string) => { - const minNum = parseFloat(`${min}`) - const maxNum = parseFloat(`${max}`) - if (!isNaN(minNum) && parseFloat(v) < minNum) { + const minNum = Number.parseFloat(`${min}`) + const maxNum = Number.parseFloat(`${max}`) + if (!isNaN(minNum) && Number.parseFloat(v) < minNum) { onChange(`${min}`) return } - if (!isNaN(maxNum) && parseFloat(v) > maxNum) + if (!isNaN(maxNum) && Number.parseFloat(v) > maxNum) onChange(`${max}`) } return ( @@ -41,7 +41,7 @@ const Input: FC = ({