Browse Source

frontend for model runtime (#1861)

Co-authored-by: Joel <iamjoel007@gmail.com>
zxhlyh 1 year ago
parent
commit
d70d61b1cb
29 changed files with 797 additions and 525 deletions
  1. 1 1
      web/app/components/app/chat/answer/index.tsx
  2. 0 22
      web/app/components/app/configuration/debug/index.tsx
  3. 1 1
      web/app/components/app/configuration/index.tsx
  4. 1 1
      web/app/components/datasets/create/step-two/index.tsx
  5. 4 4
      web/app/components/header/account-setting/model-provider-page/declarations.ts
  6. 5 3
      web/app/components/header/account-setting/model-provider-page/index.tsx
  7. 0 0
      web/app/components/header/account-setting/model-provider-page/model-display/index.tsx
  8. 12 0
      web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx
  9. 6 0
      web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx
  10. 2 1
      web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx
  11. 2 2
      web/app/components/header/account-setting/model-provider-page/model-name/index.tsx
  12. 74 28
      web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx
  13. 40 24
      web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx
  14. 46 0
      web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx
  15. 36 36
      web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx
  16. 11 1
      web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx
  17. 23 4
      web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx
  18. 1 1
      web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx
  19. 2 1
      web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx
  20. 1 1
      web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx
  21. 9 1
      web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx
  22. 3 2
      web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx
  23. 26 24
      web/app/components/share/chat/index.tsx
  24. 3 0
      web/i18n/lang/common.en.ts
  25. 3 0
      web/i18n/lang/common.zh.ts
  26. 4 8
      web/service/base.ts
  27. 3 4
      web/service/debug.ts
  28. 3 4
      web/service/share.ts
  29. 475 351
      web/yarn.lock

+ 1 - 1
web/app/components/app/chat/answer/index.tsx

@@ -275,7 +275,7 @@ const Answer: FC<IAnswerProps> = ({
                     className={cn(s.copyBtn, 'mr-1')}
                     className={cn(s.copyBtn, 'mr-1')}
                   />
                   />
                 )}
                 )}
-                {supportAnnotation && (
+                {(supportAnnotation && !item.isOpeningStatement) && (
                   <AnnotationCtrlBtn
                   <AnnotationCtrlBtn
                     appId={appId!}
                     appId={appId!}
                     messageId={id}
                     messageId={id}

+ 0 - 22
web/app/components/app/configuration/debug/index.tsx

@@ -347,7 +347,6 @@ const Debug: FC<IDebug> = ({
         }
         }
       },
       },
       onMessageEnd: (messageEnd) => {
       onMessageEnd: (messageEnd) => {
-        // TODO
         if (messageEnd.metadata?.annotation_reply) {
         if (messageEnd.metadata?.annotation_reply) {
           responseItem.id = messageEnd.id
           responseItem.id = messageEnd.id
           responseItem.annotation = ({
           responseItem.annotation = ({
@@ -382,27 +381,6 @@ const Debug: FC<IDebug> = ({
       onMessageReplace: (messageReplace) => {
       onMessageReplace: (messageReplace) => {
         responseItem.content = messageReplace.answer
         responseItem.content = messageReplace.answer
       },
       },
-      onAnnotationReply: (annotationReply) => {
-        // TODO: temp debug
-        responseItem.id = annotationReply.id
-        responseItem.content = annotationReply.answer
-        responseItem.annotation = ({
-          id: annotationReply.annotation_id,
-          authorName: annotationReply.annotation_author_name,
-        } as AnnotationType)
-        const newListWithAnswer = produce(
-          getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
-          (draft) => {
-            if (!draft.find(item => item.id === questionId))
-              draft.push({ ...questionItem })
-
-            draft.push({
-              ...responseItem,
-              id: annotationReply.id,
-            })
-          })
-        setChatList(newListWithAnswer)
-      },
       onError() {
       onError() {
         setResponsingFalse()
         setResponsingFalse()
         // role back placeholder answer
         // role back placeholder answer

+ 1 - 1
web/app/components/app/configuration/index.tsx

@@ -318,6 +318,7 @@ const Configuration: FC = () => {
       ...visionConfig,
       ...visionConfig,
       enabled: supportVision,
       enabled: supportVision,
     }, true)
     }, true)
+    setCompletionParams({})
   }
   }
 
 
   const isShowVisionConfig = !!currModel?.features?.includes(ModelFeatureEnum.vision)
   const isShowVisionConfig = !!currModel?.features?.includes(ModelFeatureEnum.vision)
@@ -656,7 +657,6 @@ const Configuration: FC = () => {
                 onCompletionParamsChange={(newParams: FormValue) => {
                 onCompletionParamsChange={(newParams: FormValue) => {
                   setCompletionParams(newParams)
                   setCompletionParams(newParams)
                 }}
                 }}
-                disabled={!hasSettedApiKey}
               />
               />
               <div className='w-[1px] h-[14px] bg-gray-200'></div>
               <div className='w-[1px] h-[14px] bg-gray-200'></div>
               <Button onClick={() => setShowConfirm(true)} className='shrink-0 mr-2 w-[70px] !h-8 !text-[13px] font-medium'>{t('appDebug.operation.resetConfig')}</Button>
               <Button onClick={() => setShowConfirm(true)} className='shrink-0 mr-2 w-[70px] !h-8 !text-[13px] font-medium'>{t('appDebug.operation.resetConfig')}</Button>

+ 1 - 1
web/app/components/datasets/create/step-two/index.tsx

@@ -587,7 +587,7 @@ const StepTwo = ({
                     </div>
                     </div>
                   </div>
                   </div>
                   <div className={s.formFooter}>
                   <div className={s.formFooter}>
-                    <Button type="primary" className={cn(s.button, '!h-8 text-primary-600')} onClick={confirmChangeCustomConfig}>{t('datasetCreation.stepTwo.preview')}</Button>
+                    <Button type="primary" className={cn(s.button, '!h-8')} onClick={confirmChangeCustomConfig}>{t('datasetCreation.stepTwo.preview')}</Button>
                     <Button className={cn(s.button, 'ml-2 !h-8')} onClick={resetRules}>{t('datasetCreation.stepTwo.reset')}</Button>
                     <Button className={cn(s.button, 'ml-2 !h-8')} onClick={resetRules}>{t('datasetCreation.stepTwo.reset')}</Button>
                   </div>
                   </div>
                 </div>
                 </div>

+ 4 - 4
web/app/components/header/account-setting/model-provider-page/declarations.ts

@@ -61,16 +61,16 @@ export enum ModelStatusEnum {
   noPermission = 'no-permission',
   noPermission = 'no-permission',
 }
 }
 
 
-export const MODEL_STATUS_TEXT = {
-  [ModelStatusEnum.noConfigure]: {
+export const MODEL_STATUS_TEXT: { [k: string]: TypeWithI18N } = {
+  'no-configure': {
     en_US: 'No Configure',
     en_US: 'No Configure',
     zh_Hans: '未配置凭据',
     zh_Hans: '未配置凭据',
   },
   },
-  [ModelStatusEnum.quotaExceeded]: {
+  'quota-exceeded': {
     en_US: 'Quota Exceeded',
     en_US: 'Quota Exceeded',
     zh_Hans: '额度不足',
     zh_Hans: '额度不足',
   },
   },
-  [ModelStatusEnum.noPermission]: {
+  'no-permission': {
     en_US: 'No Permission',
     en_US: 'No Permission',
     zh_Hans: '无使用权限',
     zh_Hans: '无使用权限',
   },
   },

+ 5 - 3
web/app/components/header/account-setting/model-provider-page/index.tsx

@@ -4,11 +4,13 @@ import SystemModelSelector from './system-model-selector'
 import ProviderAddedCard, { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './provider-added-card'
 import ProviderAddedCard, { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './provider-added-card'
 import ProviderCard from './provider-card'
 import ProviderCard from './provider-card'
 import type {
 import type {
-  ConfigurateMethodEnum,
   CustomConfigrationModelFixedFields,
   CustomConfigrationModelFixedFields,
   ModelProvider,
   ModelProvider,
 } from './declarations'
 } from './declarations'
-import { CustomConfigurationStatusEnum } from './declarations'
+import {
+  ConfigurateMethodEnum,
+  CustomConfigurationStatusEnum,
+} from './declarations'
 import {
 import {
   useDefaultModel,
   useDefaultModel,
   useUpdateModelProvidersAndModelList,
   useUpdateModelProvidersAndModelList,
@@ -57,7 +59,7 @@ const ModelProviderPage = () => {
       onSaveCallback: () => {
       onSaveCallback: () => {
         updateModelProvidersAndModelList()
         updateModelProvidersAndModelList()
 
 
-        if (customConfigrationModelFixedFields && provider.custom_configuration.status === CustomConfigurationStatusEnum.active) {
+        if (configurateMethod === ConfigurateMethodEnum.customizableModel && provider.custom_configuration.status === CustomConfigurationStatusEnum.active) {
           eventEmitter?.emit({
           eventEmitter?.emit({
             type: UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST,
             type: UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST,
             payload: provider.provider,
             payload: provider.provider,

+ 0 - 0
web/app/components/header/account-setting/model-provider-page/model-display/index.tsx


+ 12 - 0
web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx

@@ -21,6 +21,7 @@ type FormProps = {
   validating: boolean
   validating: boolean
   validatedSuccess?: boolean
   validatedSuccess?: boolean
   showOnVariableMap: Record<string, string[]>
   showOnVariableMap: Record<string, string[]>
+  isEditMode: boolean
 }
 }
 
 
 const Form: FC<FormProps> = ({
 const Form: FC<FormProps> = ({
@@ -30,11 +31,15 @@ const Form: FC<FormProps> = ({
   validating,
   validating,
   validatedSuccess,
   validatedSuccess,
   showOnVariableMap,
   showOnVariableMap,
+  isEditMode,
 }) => {
 }) => {
   const language = useLanguage()
   const language = useLanguage()
   const [changeKey, setChangeKey] = useState('')
   const [changeKey, setChangeKey] = useState('')
 
 
   const handleFormChange = (key: string, val: string) => {
   const handleFormChange = (key: string, val: string) => {
+    if (isEditMode && (key === '__model_type' || key === '__model_name'))
+      return
+
     setChangeKey(key)
     setChangeKey(key)
     const shouldClearVariable: Record<string, string | undefined> = {}
     const shouldClearVariable: Record<string, string | undefined> = {}
     if (showOnVariableMap[key]?.length) {
     if (showOnVariableMap[key]?.length) {
@@ -58,6 +63,8 @@ const Form: FC<FormProps> = ({
       if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
       if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
         return null
         return null
 
 
+      const disabed = isEditMode && (variable === '__model_type' || variable === '__model_name')
+
       return (
       return (
         <div key={variable} className='py-3'>
         <div key={variable} className='py-3'>
           <div className='py-2 text-sm text-gray-900'>
           <div className='py-2 text-sm text-gray-900'>
@@ -69,10 +76,12 @@ const Form: FC<FormProps> = ({
             }
             }
           </div>
           </div>
           <Input
           <Input
+            className={`${disabed && 'cursor-not-allowed opacity-60'}`}
             value={value[variable] as string}
             value={value[variable] as string}
             onChange={val => handleFormChange(variable, val)}
             onChange={val => handleFormChange(variable, val)}
             validated={validatedSuccess}
             validated={validatedSuccess}
             placeholder={placeholder?.[language]}
             placeholder={placeholder?.[language]}
+            disabled={disabed}
           />
           />
           {validating && changeKey === variable && <ValidatingTip />}
           {validating && changeKey === variable && <ValidatingTip />}
         </div>
         </div>
@@ -91,6 +100,8 @@ const Form: FC<FormProps> = ({
       if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
       if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
         return null
         return null
 
 
+      const disabed = isEditMode && (variable === '__model_type' || variable === '__model_name')
+
       return (
       return (
         <div key={variable} className='py-3'>
         <div key={variable} className='py-3'>
           <div className='py-2 text-sm text-gray-900'>
           <div className='py-2 text-sm text-gray-900'>
@@ -113,6 +124,7 @@ const Form: FC<FormProps> = ({
                   className={`
                   className={`
                     flex items-center px-3 py-2 rounded-lg border border-gray-100 bg-gray-25 cursor-pointer
                     flex items-center px-3 py-2 rounded-lg border border-gray-100 bg-gray-25 cursor-pointer
                     ${value[variable] === option.value && 'bg-white border-[1.5px] border-primary-400 shadow-sm'}
                     ${value[variable] === option.value && 'bg-white border-[1.5px] border-primary-400 shadow-sm'}
+                    ${disabed && '!cursor-not-allowed opacity-60'}
                   `}
                   `}
                   onClick={() => handleFormChange(variable, option.value)}
                   onClick={() => handleFormChange(variable, option.value)}
                   key={`${variable}-${option.value}`}
                   key={`${variable}-${option.value}`}

+ 6 - 0
web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx

@@ -7,6 +7,8 @@ type InputProps = {
   onFocus?: () => void
   onFocus?: () => void
   placeholder?: string
   placeholder?: string
   validated?: boolean
   validated?: boolean
+  className?: string
+  disabled?: boolean
 }
 }
 const Input: FC<InputProps> = ({
 const Input: FC<InputProps> = ({
   value,
   value,
@@ -14,6 +16,8 @@ const Input: FC<InputProps> = ({
   onFocus,
   onFocus,
   placeholder,
   placeholder,
   validated,
   validated,
+  className,
+  disabled,
 }) => {
 }) => {
   return (
   return (
     <div className='relative'>
     <div className='relative'>
@@ -26,11 +30,13 @@ const Input: FC<InputProps> = ({
           focus:bg-white focus:border-gray-300 focus:shadow-xs
           focus:bg-white focus:border-gray-300 focus:shadow-xs
           placeholder:text-sm placeholder:text-gray-400
           placeholder:text-sm placeholder:text-gray-400
           ${validated && 'pr-[30px]'}
           ${validated && 'pr-[30px]'}
+          ${className}
         `}
         `}
         placeholder={placeholder || ''}
         placeholder={placeholder || ''}
         onChange={e => onChange(e.target.value)}
         onChange={e => onChange(e.target.value)}
         onFocus={onFocus}
         onFocus={onFocus}
         value={value || ''}
         value={value || ''}
+        disabled={disabled}
       />
       />
       {
       {
         validated && (
         validated && (

+ 2 - 1
web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx

@@ -239,6 +239,7 @@ const ModelModal: FC<ModelModalProps> = ({
                 validating={validating}
                 validating={validating}
                 validatedSuccess={validatedStatusState.status === ValidatedStatus.Success}
                 validatedSuccess={validatedStatusState.status === ValidatedStatus.Success}
                 showOnVariableMap={showOnVariableMap}
                 showOnVariableMap={showOnVariableMap}
+                isEditMode={isEditMode}
               />
               />
               <div className='sticky bottom-0 flex justify-between items-center py-6 flex-wrap gap-y-2 bg-white'>
               <div className='sticky bottom-0 flex justify-between items-center py-6 flex-wrap gap-y-2 bg-white'>
                 {
                 {
@@ -313,7 +314,7 @@ const ModelModal: FC<ModelModalProps> = ({
           {
           {
             showConfirm && (
             showConfirm && (
               <ConfirmCommon
               <ConfirmCommon
-                title='Are you sure?'
+                title={t('common.modelProvider.confirmDelete')}
                 isShow={showConfirm}
                 isShow={showConfirm}
                 onCancel={() => setShowConfirm(false)}
                 onCancel={() => setShowConfirm(false)}
                 onConfirm={handleRemove}
                 onConfirm={handleRemove}

+ 2 - 2
web/app/components/header/account-setting/model-provider-page/model-name/index.tsx

@@ -43,13 +43,13 @@ const ModelName: FC<ModelNameProps> = ({
       `}
       `}
     >
     >
       <div
       <div
-        className='mr-2 truncate'
+        className='mr-1 truncate'
         title={modelItem.label[language]}
         title={modelItem.label[language]}
       >
       >
         {modelItem.label[language]}
         {modelItem.label[language]}
       </div>
       </div>
       {
       {
-        showModelType && (
+        showModelType && modelItem.model_type && (
           <ModelBadge className={`mr-0.5 ${modelTypeClassName}`}>
           <ModelBadge className={`mr-0.5 ${modelTypeClassName}`}>
             {modelTypeFormat(modelItem.model_type)}
             {modelTypeFormat(modelItem.model_type)}
           </ModelBadge>
           </ModelBadge>

+ 74 - 28
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx

@@ -1,5 +1,5 @@
 import type { FC } from 'react'
 import type { FC } from 'react'
-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
 import useSWR from 'swr'
 import useSWR from 'swr'
 import { useTranslation } from 'react-i18next'
 import { useTranslation } from 'react-i18next'
 import type {
 import type {
@@ -7,10 +7,17 @@ import type {
   FormValue,
   FormValue,
   ModelParameterRule,
   ModelParameterRule,
 } from '../declarations'
 } from '../declarations'
+import {
+  MODEL_STATUS_TEXT,
+  ModelStatusEnum,
+} from '../declarations'
 import ModelIcon from '../model-icon'
 import ModelIcon from '../model-icon'
 import ModelName from '../model-name'
 import ModelName from '../model-name'
 import ModelSelector from '../model-selector'
 import ModelSelector from '../model-selector'
-import { useTextGenerationCurrentProviderAndModelAndModelList } from '../hooks'
+import {
+  useLanguage,
+  useTextGenerationCurrentProviderAndModelAndModelList,
+} from '../hooks'
 import ParameterItem from './parameter-item'
 import ParameterItem from './parameter-item'
 import type { ParameterValue } from './parameter-item'
 import type { ParameterValue } from './parameter-item'
 import {
 import {
@@ -23,6 +30,8 @@ import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alert
 import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes'
 import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes'
 import { fetchModelParameterRules } from '@/service/common'
 import { fetchModelParameterRules } from '@/service/common'
 import Loading from '@/app/components/base/loading'
 import Loading from '@/app/components/base/loading'
+import { useProviderContext } from '@/context/provider-context'
+import TooltipPlus from '@/app/components/base/tooltip-plus'
 
 
 type ModelParameterModalProps = {
 type ModelParameterModalProps = {
   isAdvancedMode: boolean
   isAdvancedMode: boolean
@@ -32,7 +41,6 @@ type ModelParameterModalProps = {
   setModel: (model: { modelId: string; provider: string; mode?: string; features: string[] }) => void
   setModel: (model: { modelId: string; provider: string; mode?: string; features: string[] }) => void
   completionParams: FormValue
   completionParams: FormValue
   onCompletionParamsChange: (newParams: FormValue) => void
   onCompletionParamsChange: (newParams: FormValue) => void
-  disabled: boolean
 }
 }
 const stopParameerRule: ModelParameterRule = {
 const stopParameerRule: ModelParameterRule = {
   default: [],
   default: [],
@@ -42,7 +50,7 @@ const stopParameerRule: ModelParameterRule = {
   },
   },
   label: {
   label: {
     en_US: 'Stop sequences',
     en_US: 'Stop sequences',
-    zh_Hans: '停止序列 stop_sequences',
+    zh_Hans: '停止序列',
   },
   },
   name: 'stop',
   name: 'stop',
   required: false,
   required: false,
@@ -59,9 +67,10 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
   setModel,
   setModel,
   completionParams,
   completionParams,
   onCompletionParamsChange,
   onCompletionParamsChange,
-  disabled,
 }) => {
 }) => {
   const { t } = useTranslation()
   const { t } = useTranslation()
+  const language = useLanguage()
+  const { hasSettedApiKey, modelProviders } = useProviderContext()
   const [open, setOpen] = useState(false)
   const [open, setOpen] = useState(false)
   const { data: parameterRulesData, isLoading } = useSWR(`/workspaces/current/model-providers/${provider}/models/parameter-rules?model=${modelId}`, fetchModelParameterRules)
   const { data: parameterRulesData, isLoading } = useSWR(`/workspaces/current/model-providers/${provider}/models/parameter-rules?model=${modelId}`, fetchModelParameterRules)
   const {
   const {
@@ -72,7 +81,13 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
     { provider, model: modelId },
     { provider, model: modelId },
   )
   )
 
 
-  const parameterRules = parameterRulesData?.data || []
+  const hasDeprecated = !currentProvider || !currentModel
+  const modelDisabled = currentModel?.status !== ModelStatusEnum.active
+  const disabled = !hasSettedApiKey || hasDeprecated || modelDisabled
+
+  const parameterRules = useMemo(() => {
+    return parameterRulesData?.data || []
+  }, [parameterRulesData])
 
 
   const handleParamChange = (key: string, value: ParameterValue) => {
   const handleParamChange = (key: string, value: ParameterValue) => {
     onCompletionParamsChange({
     onCompletionParamsChange({
@@ -92,21 +107,6 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
     })
     })
   }
   }
 
 
-  const handleChangeParams = () => {
-    const newCompletionParams = parameterRules.reduce((acc, parameter) => {
-      if (parameter.default !== undefined)
-        acc[parameter.name] = parameter.default
-
-      return acc
-    }, {} as Record<string, any>)
-
-    onCompletionParamsChange(newCompletionParams)
-  }
-
-  useEffect(() => {
-    handleChangeParams()
-  }, [parameterRules])
-
   const handleSwitch = (key: string, value: boolean, assignValue: ParameterValue) => {
   const handleSwitch = (key: string, value: boolean, assignValue: ParameterValue) => {
     if (!value) {
     if (!value) {
       const newCompletionParams = { ...completionParams }
       const newCompletionParams = { ...completionParams }
@@ -122,6 +122,22 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
     }
     }
   }
   }
 
 
+  const handleInitialParams = () => {
+    if (parameterRules.length) {
+      const newCompletionParams = { ...completionParams }
+      Object.keys(newCompletionParams).forEach((key) => {
+        if (!parameterRules.find(item => item.name === key))
+          delete newCompletionParams[key]
+      })
+
+      onCompletionParamsChange(newCompletionParams)
+    }
+  }
+
+  useEffect(() => {
+    handleInitialParams()
+  }, [parameterRules])
+
   return (
   return (
     <PortalToFollowElem
     <PortalToFollowElem
       open={open}
       open={open}
@@ -149,22 +165,48 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
                 />
                 />
               )
               )
             }
             }
+            {
+              !currentProvider && (
+                <ModelIcon
+                  className='mr-1.5 !w-5 !h-5'
+                  provider={modelProviders.find(item => item.provider === provider)}
+                  modelName={modelId}
+                />
+              )
+            }
             {
             {
               currentModel && (
               currentModel && (
                 <ModelName
                 <ModelName
                   className='mr-1.5 text-gray-900'
                   className='mr-1.5 text-gray-900'
                   modelItem={currentModel}
                   modelItem={currentModel}
-                  showMode={isAdvancedMode}
+                  showMode
                   modeClassName='!text-[#444CE7] !border-[#A4BCFD]'
                   modeClassName='!text-[#444CE7] !border-[#A4BCFD]'
-                  showFeatures={isAdvancedMode}
+                  showFeatures
                   featuresClassName='!text-[#444CE7] !border-[#A4BCFD]'
                   featuresClassName='!text-[#444CE7] !border-[#A4BCFD]'
                 />
                 />
               )
               )
             }
             }
+            {
+              !currentModel && (
+                <div className='mr-1 text-[13px] font-medium text-gray-900 truncate'>
+                  {modelId}
+                </div>
+              )
+            }
             {
             {
               disabled
               disabled
                 ? (
                 ? (
-                  <AlertTriangle className='w-4 h-4 text-[#F79009]' />
+                  <TooltipPlus
+                    popupContent={
+                      hasDeprecated
+                        ? t('common.modelProvider.deprecated')
+                        : (modelDisabled && currentModel)
+                          ? MODEL_STATUS_TEXT[currentModel.status as string][language]
+                          : ''
+                    }
+                  >
+                    <AlertTriangle className='w-4 h-4 text-[#F79009]' />
+                  </TooltipPlus>
                 )
                 )
                 : (
                 : (
                   <SlidersH className='w-4 h-4 text-indigo-600' />
                   <SlidersH className='w-4 h-4 text-indigo-600' />
@@ -178,7 +220,7 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
               <CubeOutline className='mr-2 w-4 h-4 text-primary-600' />
               <CubeOutline className='mr-2 w-4 h-4 text-primary-600' />
               {t('common.modelProvider.modelAndParameters')}
               {t('common.modelProvider.modelAndParameters')}
             </div>
             </div>
-            <div className='px-10 pt-4 pb-8'>
+            <div className='max-h-[480px] px-10 pt-4 pb-8 overflow-y-auto'>
               <div className='flex items-center justify-between h-8'>
               <div className='flex items-center justify-between h-8'>
                 <div className='text-sm font-medium text-gray-900'>
                 <div className='text-sm font-medium text-gray-900'>
                   {t('common.modelProvider.model')}
                   {t('common.modelProvider.model')}
@@ -189,14 +231,18 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
                   onSelect={handleChangeModel}
                   onSelect={handleChangeModel}
                 />
                 />
               </div>
               </div>
-              <div className='my-5 h-[1px] bg-gray-100' />
+              {
+                !!parameterRules.length && (
+                  <div className='my-5 h-[1px] bg-gray-100' />
+                )
+              }
               {
               {
                 isLoading && (
                 isLoading && (
-                  <Loading />
+                  <div className='mt-5'><Loading /></div>
                 )
                 )
               }
               }
               {
               {
-                !isLoading && (
+                !isLoading && !!parameterRules.length && (
                   [
                   [
                     ...parameterRules,
                     ...parameterRules,
                     ...(isAdvancedMode ? [stopParameerRule] : []),
                     ...(isAdvancedMode ? [stopParameerRule] : []),

+ 40 - 24
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx

@@ -29,7 +29,37 @@ const ParameterItem: FC<ParameterItemProps> = ({
   const language = useLanguage()
   const language = useLanguage()
   const [localValue, setLocalValue] = useState(value)
   const [localValue, setLocalValue] = useState(value)
   const mergedValue = isNullOrUndefined(value) ? localValue : value
   const mergedValue = isNullOrUndefined(value) ? localValue : value
-  const renderValue = mergedValue === undefined ? parameterRule.default : mergedValue
+
+  const getDefaultValue = () => {
+    let defaultValue: ParameterValue
+
+    if (parameterRule.type === 'int' || parameterRule.type === 'float') {
+      if (isNullOrUndefined(parameterRule.default)) {
+        if (parameterRule.min)
+          defaultValue = parameterRule.min
+        else
+          defaultValue = 0
+      }
+      else {
+        defaultValue = parameterRule.default
+      }
+    }
+
+    if (parameterRule.type === 'string' && !parameterRule.options?.length)
+      defaultValue = parameterRule.default || ''
+
+    if (parameterRule.type === 'string' && parameterRule.options?.length)
+      defaultValue = parameterRule.default || ''
+
+    if (parameterRule.type === 'boolean')
+      defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : false
+
+    if (parameterRule.type === 'tag')
+      defaultValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : []
+
+    return defaultValue
+  }
+  const renderValue = isNullOrUndefined(mergedValue) ? getDefaultValue() : mergedValue
 
 
   const handleChange = (v: ParameterValue) => {
   const handleChange = (v: ParameterValue) => {
     setLocalValue(v)
     setLocalValue(v)
@@ -73,22 +103,8 @@ const ParameterItem: FC<ParameterItemProps> = ({
     if (onSwitch) {
     if (onSwitch) {
       let assignValue: ParameterValue = localValue
       let assignValue: ParameterValue = localValue
 
 
-      if (isNullOrUndefined(localValue)) {
-        if (parameterRule.type === 'int' || parameterRule.type === 'float')
-          assignValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : 0
-
-        if (parameterRule.type === 'string' && !parameterRule.options?.length)
-          assignValue = parameterRule.default || ''
-
-        if (parameterRule.type === 'string' && parameterRule.options?.length)
-          assignValue = parameterRule.options[0]
-
-        if (parameterRule.type === 'boolean')
-          assignValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : false
-
-        if (parameterRule.type === 'tag')
-          assignValue = !isNullOrUndefined(parameterRule.default) ? parameterRule.default : []
-      }
+      if (isNullOrUndefined(localValue))
+        assignValue = getDefaultValue()
 
 
       onSwitch(checked, assignValue)
       onSwitch(checked, assignValue)
     }
     }
@@ -145,7 +161,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
           <div className='flex items-center'>
           <div className='flex items-center'>
             <Slider
             <Slider
               className='w-[120px]'
               className='w-[120px]'
-              value={isNullOrUndefined(renderValue) ? 0 : +renderValue!}
+              value={renderValue as number}
               min={parameterRule.min}
               min={parameterRule.min}
               max={parameterRule.max}
               max={parameterRule.max}
               step={+`0.${parameterRule.precision || 0}`}
               step={+`0.${parameterRule.precision || 0}`}
@@ -157,7 +173,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
               max={parameterRule.max}
               max={parameterRule.max}
               min={parameterRule.min}
               min={parameterRule.min}
               step={+`0.${parameterRule.precision || 0}`}
               step={+`0.${parameterRule.precision || 0}`}
-              value={isNullOrUndefined(renderValue) ? 0 : +renderValue!}
+              value={renderValue as string}
               onChange={handleNumberInputChange}
               onChange={handleNumberInputChange}
             />
             />
           </div>
           </div>
@@ -167,7 +183,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
         parameterRule.type === 'boolean' && (
         parameterRule.type === 'boolean' && (
           <Radio.Group
           <Radio.Group
             className='w-[200px] flex items-center'
             className='w-[200px] flex items-center'
-            value={isNullOrUndefined(renderValue) ? 1 : 0}
+            value={renderValue ? 1 : 0}
             onChange={handleRadioChange}
             onChange={handleRadioChange}
           >
           >
             <Radio value={1} className='!mr-1 w-[94px]'>True</Radio>
             <Radio value={1} className='!mr-1 w-[94px]'>True</Radio>
@@ -180,7 +196,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
           <input
           <input
             type='number'
             type='number'
             className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
             className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
-            value={(isNullOrUndefined(renderValue) ? '' : renderValue) as string}
+            value={renderValue as string}
             onChange={handleNumberInputChange}
             onChange={handleNumberInputChange}
           />
           />
         )
         )
@@ -189,13 +205,13 @@ const ParameterItem: FC<ParameterItemProps> = ({
         parameterRule.type === 'string' && !parameterRule.options?.length && (
         parameterRule.type === 'string' && !parameterRule.options?.length && (
           <input
           <input
             className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
             className='flex items-center px-3 w-[200px] h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900'
-            value={(isNullOrUndefined(renderValue) ? '' : renderValue) as string}
+            value={renderValue as string}
             onChange={handleStringInputChange}
             onChange={handleStringInputChange}
           />
           />
         )
         )
       }
       }
       {
       {
-        parameterRule.type === 'string' && parameterRule?.options?.length && (
+        parameterRule.type === 'string' && !!parameterRule?.options?.length && (
           <SimpleSelect
           <SimpleSelect
             className='!py-0'
             className='!py-0'
             wrapperClassName='!w-[200px] !h-8'
             wrapperClassName='!w-[200px] !h-8'
@@ -209,7 +225,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
         parameterRule.type === 'tag' && (
         parameterRule.type === 'tag' && (
           <div className='w-[200px]'>
           <div className='w-[200px]'>
             <TagInput
             <TagInput
-              items={isNullOrUndefined(renderValue) ? [] : (renderValue as string[])}
+              items={renderValue as string[]}
               onChange={handleTagChange}
               onChange={handleTagChange}
               customizedConfirmKey='Tab'
               customizedConfirmKey='Tab'
             />
             />

+ 46 - 0
web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx

@@ -0,0 +1,46 @@
+import type { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import ModelIcon from '../model-icon'
+import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
+import { useProviderContext } from '@/context/provider-context'
+import TooltipPlus from '@/app/components/base/tooltip-plus'
+
+type ModelTriggerProps = {
+  modelName: string
+  providerName: string
+  className?: string
+}
+const ModelTrigger: FC<ModelTriggerProps> = ({
+  modelName,
+  providerName,
+  className,
+}) => {
+  const { t } = useTranslation()
+  const { modelProviders } = useProviderContext()
+  const currentProvider = modelProviders.find(provider => provider.provider === providerName)
+
+  return (
+    <div
+      className={`
+        group flex items-center px-2 h-8 rounded-lg bg-[#FFFAEB] cursor-pointer
+        ${className}
+      `}
+    >
+      <ModelIcon
+        className='shrink-0 mr-1.5'
+        provider={currentProvider}
+        modelName={modelName}
+      />
+      <div className='mr-1 text-[13px] font-medium text-gray-800 truncate'>
+        {modelName}
+      </div>
+      <div className='shrink-0 flex items-center justify-center w-4 h-4'>
+        <TooltipPlus popupContent={t('common.modelProvider.deprecated')}>
+          <AlertTriangle className='w-4 h-4 text-[#F79009]' />
+        </TooltipPlus>
+      </div>
+    </div>
+  )
+}
+
+export default ModelTrigger

+ 36 - 36
web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx

@@ -6,10 +6,10 @@ import {
   ModelFeatureTextEnum,
   ModelFeatureTextEnum,
 } from '../declarations'
 } from '../declarations'
 import {
 import {
-  MagicBox,
+  // MagicBox,
   MagicEyes,
   MagicEyes,
-  MagicWand,
-  Robot,
+  // MagicWand,
+  // Robot,
 } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices'
 } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices'
 import TooltipPlus from '@/app/components/base/tooltip-plus'
 import TooltipPlus from '@/app/components/base/tooltip-plus'
 
 
@@ -23,41 +23,41 @@ const FeatureIcon: FC<FeatureIconProps> = ({
 }) => {
 }) => {
   const { t } = useTranslation()
   const { t } = useTranslation()
 
 
-  if (feature === ModelFeatureEnum.agentThought) {
-    return (
-      <TooltipPlus
-        popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })}
-      >
-        <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
-          <Robot className='w-3 h-3' />
-        </ModelBadge>
-      </TooltipPlus>
-    )
-  }
+  // if (feature === ModelFeatureEnum.agentThought) {
+  //   return (
+  //     <TooltipPlus
+  //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })}
+  //     >
+  //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
+  //         <Robot className='w-3 h-3' />
+  //       </ModelBadge>
+  //     </TooltipPlus>
+  //   )
+  // }
 
 
-  if (feature === ModelFeatureEnum.toolCall) {
-    return (
-      <TooltipPlus
-        popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })}
-      >
-        <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
-          <MagicWand className='w-3 h-3' />
-        </ModelBadge>
-      </TooltipPlus>
-    )
-  }
+  // if (feature === ModelFeatureEnum.toolCall) {
+  //   return (
+  //     <TooltipPlus
+  //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })}
+  //     >
+  //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
+  //         <MagicWand className='w-3 h-3' />
+  //       </ModelBadge>
+  //     </TooltipPlus>
+  //   )
+  // }
 
 
-  if (feature === ModelFeatureEnum.multiToolCall) {
-    return (
-      <TooltipPlus
-        popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })}
-      >
-        <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
-          <MagicBox className='w-3 h-3' />
-        </ModelBadge>
-      </TooltipPlus>
-    )
-  }
+  // if (feature === ModelFeatureEnum.multiToolCall) {
+  //   return (
+  //     <TooltipPlus
+  //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })}
+  //     >
+  //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
+  //         <MagicBox className='w-3 h-3' />
+  //       </ModelBadge>
+  //     </TooltipPlus>
+  //   )
+  // }
 
 
   if (feature === ModelFeatureEnum.vision) {
   if (feature === ModelFeatureEnum.vision) {
     return (
     return (

+ 11 - 1
web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx

@@ -8,6 +8,7 @@ import type {
 import { useCurrentProviderAndModel } from '../hooks'
 import { useCurrentProviderAndModel } from '../hooks'
 import ModelTrigger from './model-trigger'
 import ModelTrigger from './model-trigger'
 import EmptyTrigger from './empty-trigger'
 import EmptyTrigger from './empty-trigger'
+import DeprecatedModelTrigger from './deprecated-model-trigger'
 import Popup from './popup'
 import Popup from './popup'
 import {
 import {
   PortalToFollowElem,
   PortalToFollowElem,
@@ -77,7 +78,16 @@ const ModelSelector: FC<ModelSelectorProps> = ({
             )
             )
           }
           }
           {
           {
-            !currentModel && (
+            !currentModel && defaultModel && (
+              <DeprecatedModelTrigger
+                modelName={defaultModel?.model || ''}
+                providerName={defaultModel?.provider || ''}
+                className={triggerClassName}
+              />
+            )
+          }
+          {
+            !defaultModel && (
               <EmptyTrigger
               <EmptyTrigger
                 open={open}
                 open={open}
                 className={triggerClassName}
                 className={triggerClassName}

+ 23 - 4
web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx

@@ -3,10 +3,16 @@ import type {
   Model,
   Model,
   ModelItem,
   ModelItem,
 } from '../declarations'
 } from '../declarations'
+import {
+  MODEL_STATUS_TEXT,
+  ModelStatusEnum,
+} from '../declarations'
+import { useLanguage } from '../hooks'
 import ModelIcon from '../model-icon'
 import ModelIcon from '../model-icon'
 import ModelName from '../model-name'
 import ModelName from '../model-name'
-// import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
+import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
 import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
 import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows'
+import TooltipPlus from '@/app/components/base/tooltip-plus'
 
 
 type ModelTriggerProps = {
 type ModelTriggerProps = {
   open: boolean
   open: boolean
@@ -20,12 +26,15 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
   model,
   model,
   className,
   className,
 }) => {
 }) => {
+  const language = useLanguage()
+
   return (
   return (
     <div
     <div
       className={`
       className={`
         group flex items-center px-2 h-8 rounded-lg bg-gray-100 hover:bg-gray-200 cursor-pointer
         group flex items-center px-2 h-8 rounded-lg bg-gray-100 hover:bg-gray-200 cursor-pointer
         ${className}
         ${className}
         ${open && '!bg-gray-200'}
         ${open && '!bg-gray-200'}
+        ${model.status !== ModelStatusEnum.active && '!bg-[#FFFAEB]'}
       `}
       `}
     >
     >
       <ModelIcon
       <ModelIcon
@@ -40,9 +49,19 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
         showFeatures
         showFeatures
       />
       />
       <div className='shrink-0 flex items-center justify-center w-4 h-4'>
       <div className='shrink-0 flex items-center justify-center w-4 h-4'>
-        <ChevronDown
-          className='w-3.5 h-3.5 text-gray-500'
-        />
+        {
+          model.status !== ModelStatusEnum.active
+            ? (
+              <TooltipPlus popupContent={MODEL_STATUS_TEXT[model.status][language]}>
+                <AlertTriangle className='w-4 h-4 text-[#F79009]' />
+              </TooltipPlus>
+            )
+            : (
+              <ChevronDown
+                className='w-3.5 h-3.5 text-gray-500'
+              />
+            )
+        }
       </div>
       </div>
     </div>
     </div>
   )
   )

+ 1 - 1
web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx

@@ -102,7 +102,7 @@ const PopupItem: FC<PopupItemProps> = ({
                 showFeatures
                 showFeatures
               />
               />
               {
               {
-                defaultModel?.model === modelItem.model && (
+                defaultModel?.model === modelItem.model && defaultModel.provider === currentProvider.provider && (
                   <Check className='shrink-0 w-4 h-4 text-primary-600' />
                   <Check className='shrink-0 w-4 h-4 text-primary-600' />
                 )
                 )
               }
               }

+ 2 - 1
web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx

@@ -21,6 +21,7 @@ import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/a
 import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
 import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
 import { fetchModelProviderModelList } from '@/service/common'
 import { fetchModelProviderModelList } from '@/service/common'
 import { useEventEmitterContextContext } from '@/context/event-emitter'
 import { useEventEmitterContextContext } from '@/context/event-emitter'
+import { IS_CE_EDITION } from '@/config'
 
 
 export const UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST = 'UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST'
 export const UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST = 'UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST'
 type ProviderAddedCardProps = {
 type ProviderAddedCardProps = {
@@ -40,7 +41,7 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
   const systemConfig = provider.system_configuration
   const systemConfig = provider.system_configuration
   const hasModelList = fetched && !!modelList.length
   const hasModelList = fetched && !!modelList.length
-  const showQuota = systemConfig.enabled || ['minimax', 'spark', 'zhipuai', 'anthropic'].includes(provider.provider)
+  const showQuota = systemConfig.enabled && ['minimax', 'spark', 'zhipuai', 'anthropic', 'openai'].includes(provider.provider) && !IS_CE_EDITION
 
 
   const getModelList = async (providerName: string) => {
   const getModelList = async (providerName: string) => {
     if (loading)
     if (loading)

+ 1 - 1
web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx

@@ -78,9 +78,9 @@ const ModelList: FC<ModelListProps> = ({
               className={`
               className={`
                 group flex items-center pl-2 pr-2.5 h-8 rounded-lg
                 group flex items-center pl-2 pr-2.5 h-8 rounded-lg
                 ${canCustomConfig && 'hover:bg-gray-50'}
                 ${canCustomConfig && 'hover:bg-gray-50'}
+                ${model.deprecated && 'opacity-60'}
               `}
               `}
             >
             >
-              <div className='shrink-0 mr-2' style={{ background: provider.icon_small[language] }} />
               <ModelIcon
               <ModelIcon
                 className='shrink-0 mr-2'
                 className='shrink-0 mr-2'
                 provider={provider}
                 provider={provider}

+ 9 - 1
web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx

@@ -14,6 +14,7 @@ import {
 import PriorityUseTip from './priority-use-tip'
 import PriorityUseTip from './priority-use-tip'
 import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
 import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
 import Button from '@/app/components/base/button'
 import Button from '@/app/components/base/button'
+import TooltipPlus from '@/app/components/base/tooltip-plus'
 
 
 type QuotaPanelProps = {
 type QuotaPanelProps = {
   provider: ModelProvider
   provider: ModelProvider
@@ -32,12 +33,19 @@ const QuotaPanel: FC<QuotaPanelProps> = ({
   const priorityUseType = provider.preferred_provider_type
   const priorityUseType = provider.preferred_provider_type
   const systemConfig = provider.system_configuration
   const systemConfig = provider.system_configuration
   const currentQuota = systemConfig.enabled && systemConfig.quota_configurations.find(item => item.quota_type === systemConfig.current_quota_type)
   const currentQuota = systemConfig.enabled && systemConfig.quota_configurations.find(item => item.quota_type === systemConfig.current_quota_type)
+  const openaiOrAnthropic = ['openai', 'anthropic'].includes(provider.provider)
 
 
   return (
   return (
     <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'>
     <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'>
       <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'>
       <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'>
         {t('common.modelProvider.quota')}
         {t('common.modelProvider.quota')}
-        <InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' />
+        <TooltipPlus popupContent={
+          openaiOrAnthropic
+            ? t('common.modelProvider.card.tip')
+            : t('common.modelProvider.quotaTip')
+        }>
+          <InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' />
+        </TooltipPlus>
       </div>
       </div>
       {
       {
         currentQuota && (
         currentQuota && (

+ 3 - 2
web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx

@@ -21,6 +21,7 @@ import s from './index.module.css'
 import { Plus, Settings01 } from '@/app/components/base/icons/src/vender/line/general'
 import { Plus, Settings01 } from '@/app/components/base/icons/src/vender/line/general'
 import { CoinsStacked01 } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
 import { CoinsStacked01 } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
 import Button from '@/app/components/base/button'
 import Button from '@/app/components/base/button'
+import { IS_CE_EDITION } from '@/config'
 
 
 type ProviderCardProps = {
 type ProviderCardProps = {
   provider: ModelProvider
   provider: ModelProvider
@@ -54,7 +55,7 @@ const ProviderCard: FC<ProviderCardProps> = ({
   }
   }
   const handleFreeQuota = useFreeQuota(handleFreeQuotaSuccess)
   const handleFreeQuota = useFreeQuota(handleFreeQuotaSuccess)
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
-  const canGetFreeQuota = ['mininmax', 'spark', 'zhipuai'].includes(provider.provider)
+  const canGetFreeQuota = ['mininmax', 'spark', 'zhipuai'].includes(provider.provider) && !IS_CE_EDITION
 
 
   return (
   return (
     <div
     <div
@@ -135,7 +136,7 @@ const ProviderCard: FC<ProviderCardProps> = ({
             })
             })
           }
           }
           {
           {
-            provider.provider === 'anthropic' && (
+            provider.provider === 'anthropic' && !IS_CE_EDITION && (
               <Button
               <Button
                 className='h-7 text-xs text-gray-700'
                 className='h-7 text-xs text-gray-700'
                 onClick={handlePay}
                 onClick={handlePay}

+ 26 - 24
web/app/components/share/chat/index.tsx

@@ -43,6 +43,7 @@ import Confirm from '@/app/components/base/confirm'
 import type { VisionFile, VisionSettings } from '@/types/app'
 import type { VisionFile, VisionSettings } from '@/types/app'
 import { Resolution, TransferMethod } from '@/types/app'
 import { Resolution, TransferMethod } from '@/types/app'
 import { fetchFileUploadConfig } from '@/service/common'
 import { fetchFileUploadConfig } from '@/service/common'
+import type { Annotation as AnnotationType } from '@/models/log'
 
 
 export type IMainProps = {
 export type IMainProps = {
   isInstalledApp?: boolean
   isInstalledApp?: boolean
@@ -582,23 +583,40 @@ const Main: FC<IMainProps> = ({
         }
         }
         setResponsingFalse()
         setResponsingFalse()
       },
       },
-      onMessageEnd: isInstalledApp
-        ? (messageEnd) => {
-          if (!isInstalledApp)
-            return
-          responseItem.citation = messageEnd.retriever_resources
-
+      onMessageEnd: (messageEnd) => {
+        if (messageEnd.metadata?.annotation_reply) {
+          responseItem.id = messageEnd.id
+          responseItem.annotation = ({
+            id: messageEnd.metadata.annotation_reply.id,
+            authorName: messageEnd.metadata.annotation_reply.account.name,
+          } as AnnotationType)
           const newListWithAnswer = produce(
           const newListWithAnswer = produce(
             getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
             getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
             (draft) => {
             (draft) => {
               if (!draft.find(item => item.id === questionId))
               if (!draft.find(item => item.id === questionId))
                 draft.push({ ...questionItem })
                 draft.push({ ...questionItem })
 
 
-              draft.push({ ...responseItem })
+              draft.push({
+                ...responseItem,
+              })
             })
             })
           setChatList(newListWithAnswer)
           setChatList(newListWithAnswer)
+          return
         }
         }
-        : undefined,
+        // not support show citation
+        // responseItem.citation = messageEnd.retriever_resources
+        if (!isInstalledApp)
+          return
+        const newListWithAnswer = produce(
+          getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
+          (draft) => {
+            if (!draft.find(item => item.id === questionId))
+              draft.push({ ...questionItem })
+
+            draft.push({ ...responseItem })
+          })
+        setChatList(newListWithAnswer)
+      },
       onMessageReplace: (messageReplace) => {
       onMessageReplace: (messageReplace) => {
         if (isInstalledApp) {
         if (isInstalledApp) {
           responseItem.content = messageReplace.answer
           responseItem.content = messageReplace.answer
@@ -615,22 +633,6 @@ const Main: FC<IMainProps> = ({
           ))
           ))
         }
         }
       },
       },
-      onAnnotationReply: (annotationReply) => {
-        responseItem.content = annotationReply.answer
-        const newListWithAnswer = produce(
-          getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
-          (draft) => {
-            if (!draft.find(item => item.id === questionId))
-              draft.push({ ...questionItem })
-
-            draft.push({
-              ...responseItem,
-              id: annotationReply.id,
-            })
-          })
-        setChatList(newListWithAnswer)
-        tempNewConversationId = annotationReply.conversation_id
-      },
       onError() {
       onError() {
         setResponsingFalse()
         setResponsingFalse()
         // role back placeholder answer
         // role back placeholder answer

+ 3 - 0
web/i18n/lang/common.en.ts

@@ -300,6 +300,9 @@ const translation = {
     buyQuota: 'Buy Quota',
     buyQuota: 'Buy Quota',
     getFreeTokens: 'Get free Tokens',
     getFreeTokens: 'Get free Tokens',
     priorityUsing: 'Prioritize using',
     priorityUsing: 'Prioritize using',
+    deprecated: 'Deprecated',
+    confirmDelete: 'confirm deletion?',
+    quotaTip: 'Remaining available free tokens',
   },
   },
   dataSource: {
   dataSource: {
     add: 'Add a data source',
     add: 'Add a data source',

+ 3 - 0
web/i18n/lang/common.zh.ts

@@ -300,6 +300,9 @@ const translation = {
     buyQuota: '购买额度',
     buyQuota: '购买额度',
     getFreeTokens: '获得免费 Tokens',
     getFreeTokens: '获得免费 Tokens',
     priorityUsing: '优先使用',
     priorityUsing: '优先使用',
+    deprecated: '已弃用',
+    confirmDelete: '确认删除?',
+    quotaTip: '剩余免费额度',
   },
   },
   dataSource: {
   dataSource: {
     add: '添加数据源',
     add: '添加数据源',

+ 4 - 8
web/service/base.ts

@@ -47,7 +47,6 @@ type IOtherOptions = {
   onThought?: IOnThought
   onThought?: IOnThought
   onMessageEnd?: IOnMessageEnd
   onMessageEnd?: IOnMessageEnd
   onMessageReplace?: IOnMessageReplace
   onMessageReplace?: IOnMessageReplace
-  onAnnotationReply?: IOnAnnotationReply
   onError?: IOnError
   onError?: IOnError
   onCompleted?: IOnCompleted // for stream
   onCompleted?: IOnCompleted // for stream
   getAbortController?: (abortController: AbortController) => void
   getAbortController?: (abortController: AbortController) => void
@@ -81,7 +80,7 @@ export function format(text: string) {
   return res.replaceAll('\n', '<br/>').replaceAll('```', '')
   return res.replaceAll('\n', '<br/>').replaceAll('```', '')
 }
 }
 
 
-const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnCompleted, onThought?: IOnThought, onMessageEnd?: IOnMessageEnd, onMessageReplace?: IOnMessageReplace, onAnnotationReply?: IOnAnnotationReply) => {
+const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnCompleted, onThought?: IOnThought, onMessageEnd?: IOnMessageEnd, onMessageReplace?: IOnMessageReplace) => {
   if (!response.ok)
   if (!response.ok)
     throw new Error('Network response was not ok')
     throw new Error('Network response was not ok')
 
 
@@ -137,14 +136,12 @@ const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnComp
               onThought?.(bufferObj as ThoughtItem)
               onThought?.(bufferObj as ThoughtItem)
             }
             }
             else if (bufferObj.event === 'message_end') {
             else if (bufferObj.event === 'message_end') {
+              console.log(bufferObj)
               onMessageEnd?.(bufferObj as MessageEnd)
               onMessageEnd?.(bufferObj as MessageEnd)
             }
             }
             else if (bufferObj.event === 'message_replace') {
             else if (bufferObj.event === 'message_replace') {
               onMessageReplace?.(bufferObj as MessageReplace)
               onMessageReplace?.(bufferObj as MessageReplace)
             }
             }
-            else if (bufferObj.event === 'annotation') {
-              onAnnotationReply?.(bufferObj as AnnotationReply)
-            }
           }
           }
         })
         })
         buffer = lines[lines.length - 1]
         buffer = lines[lines.length - 1]
@@ -350,7 +347,7 @@ export const upload = (options: any, isPublicAPI?: boolean, url?: string): Promi
   })
   })
 }
 }
 
 
-export const ssePost = (url: string, fetchOptions: FetchOptionType, { isPublicAPI = false, onData, onCompleted, onThought, onMessageEnd, onMessageReplace, onAnnotationReply, onError, getAbortController }: IOtherOptions) => {
+export const ssePost = (url: string, fetchOptions: FetchOptionType, { isPublicAPI = false, onData, onCompleted, onThought, onMessageEnd, onMessageReplace, onError, getAbortController }: IOtherOptions) => {
   const abortController = new AbortController()
   const abortController = new AbortController()
 
 
   const options = Object.assign({}, baseOptions, {
   const options = Object.assign({}, baseOptions, {
@@ -382,14 +379,13 @@ export const ssePost = (url: string, fetchOptions: FetchOptionType, { isPublicAP
       }
       }
       return handleStream(res, (str: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => {
       return handleStream(res, (str: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => {
         if (moreInfo.errorMessage) {
         if (moreInfo.errorMessage) {
-          // debugger
           onError?.(moreInfo.errorMessage, moreInfo.errorCode)
           onError?.(moreInfo.errorMessage, moreInfo.errorCode)
           if (moreInfo.errorMessage !== 'AbortError: The user aborted a request.')
           if (moreInfo.errorMessage !== 'AbortError: The user aborted a request.')
             Toast.notify({ type: 'error', message: moreInfo.errorMessage })
             Toast.notify({ type: 'error', message: moreInfo.errorMessage })
           return
           return
         }
         }
         onData?.(str, isFirstMessage, moreInfo)
         onData?.(str, isFirstMessage, moreInfo)
-      }, onCompleted, onThought, onMessageEnd, onMessageReplace, onAnnotationReply)
+      }, onCompleted, onThought, onMessageEnd, onMessageReplace)
     }).catch((e) => {
     }).catch((e) => {
       if (e.toString() !== 'AbortError: The user aborted a request.')
       if (e.toString() !== 'AbortError: The user aborted a request.')
         Toast.notify({ type: 'error', message: e })
         Toast.notify({ type: 'error', message: e })

+ 3 - 4
web/service/debug.ts

@@ -1,4 +1,4 @@
-import type { IOnAnnotationReply, IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnMessageReplace } from './base'
+import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnMessageReplace } from './base'
 import { get, post, ssePost } from './base'
 import { get, post, ssePost } from './base'
 import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug'
 import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug'
 import type { ModelModeType } from '@/types/app'
 import type { ModelModeType } from '@/types/app'
@@ -10,12 +10,11 @@ export type AutomaticRes = {
   opening_statement: string
   opening_statement: string
 }
 }
 
 
-export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace, onAnnotationReply }: {
+export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace }: {
   onData: IOnData
   onData: IOnData
   onCompleted: IOnCompleted
   onCompleted: IOnCompleted
   onMessageEnd: IOnMessageEnd
   onMessageEnd: IOnMessageEnd
   onMessageReplace: IOnMessageReplace
   onMessageReplace: IOnMessageReplace
-  onAnnotationReply: IOnAnnotationReply
   onError: IOnError
   onError: IOnError
   getAbortController?: (abortController: AbortController) => void
   getAbortController?: (abortController: AbortController) => void
 }) => {
 }) => {
@@ -24,7 +23,7 @@ export const sendChatMessage = async (appId: string, body: Record<string, any>,
       ...body,
       ...body,
       response_mode: 'streaming',
       response_mode: 'streaming',
     },
     },
-  }, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace, onAnnotationReply })
+  }, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace })
 }
 }
 
 
 export const stopChatMessageResponding = async (appId: string, taskId: string) => {
 export const stopChatMessageResponding = async (appId: string, taskId: string) => {

+ 3 - 4
web/service/share.ts

@@ -1,4 +1,4 @@
-import type { IOnAnnotationReply, IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnMessageReplace } from './base'
+import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnMessageReplace } from './base'
 import {
 import {
   del as consoleDel, get as consoleGet, patch as consolePatch, post as consolePost,
   del as consoleDel, get as consoleGet, patch as consolePatch, post as consolePost,
   delPublic as del, getPublic as get, patchPublic as patch, postPublic as post, ssePost,
   delPublic as del, getPublic as get, patchPublic as patch, postPublic as post, ssePost,
@@ -22,13 +22,12 @@ function getUrl(url: string, isInstalledApp: boolean, installedAppId: string) {
   return isInstalledApp ? `installed-apps/${installedAppId}/${url.startsWith('/') ? url.slice(1) : url}` : url
   return isInstalledApp ? `installed-apps/${installedAppId}/${url.startsWith('/') ? url.slice(1) : url}` : url
 }
 }
 
 
-export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace, onAnnotationReply }: {
+export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onError, getAbortController, onMessageEnd, onMessageReplace }: {
   onData: IOnData
   onData: IOnData
   onCompleted: IOnCompleted
   onCompleted: IOnCompleted
   onError: IOnError
   onError: IOnError
   onMessageEnd?: IOnMessageEnd
   onMessageEnd?: IOnMessageEnd
   onMessageReplace?: IOnMessageReplace
   onMessageReplace?: IOnMessageReplace
-  onAnnotationReply: IOnAnnotationReply
   getAbortController?: (abortController: AbortController) => void
   getAbortController?: (abortController: AbortController) => void
 }, isInstalledApp: boolean, installedAppId = '') => {
 }, isInstalledApp: boolean, installedAppId = '') => {
   return ssePost(getUrl('chat-messages', isInstalledApp, installedAppId), {
   return ssePost(getUrl('chat-messages', isInstalledApp, installedAppId), {
@@ -36,7 +35,7 @@ export const sendChatMessage = async (body: Record<string, any>, { onData, onCom
       ...body,
       ...body,
       response_mode: 'streaming',
       response_mode: 'streaming',
     },
     },
-  }, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController, onMessageEnd, onMessageReplace, onAnnotationReply })
+  }, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, getAbortController, onMessageEnd, onMessageReplace })
 }
 }
 
 
 export const stopChatMessageResponding = async (appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {
 export const stopChatMessageResponding = async (appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {

File diff suppressed because it is too large
+ 475 - 351
web/yarn.lock


Some files were not shown because too many files changed in this diff