Unverified Commit d70d61b1 authored by zxhlyh's avatar zxhlyh Committed by GitHub

frontend for model runtime (#1861)

Co-authored-by: 's avatarJoel <iamjoel007@gmail.com>
parent d069c668
...@@ -275,7 +275,7 @@ const Answer: FC<IAnswerProps> = ({ ...@@ -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}
......
...@@ -347,7 +347,6 @@ const Debug: FC<IDebug> = ({ ...@@ -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> = ({ ...@@ -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
......
...@@ -318,6 +318,7 @@ const Configuration: FC = () => { ...@@ -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 = () => { ...@@ -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>
......
...@@ -587,7 +587,7 @@ const StepTwo = ({ ...@@ -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>
......
...@@ -61,16 +61,16 @@ export enum ModelStatusEnum { ...@@ -61,16 +61,16 @@ export enum ModelStatusEnum {
noPermission = 'no-permission', noPermission = 'no-permission',
} }
export const MODEL_STATUS_TEXT = { export const MODEL_STATUS_TEXT: { [k: string]: TypeWithI18N } = {
[ModelStatusEnum.noConfigure]: { '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: '无使用权限',
}, },
......
...@@ -4,11 +4,13 @@ import SystemModelSelector from './system-model-selector' ...@@ -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 = () => { ...@@ -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,
......
...@@ -21,6 +21,7 @@ type FormProps = { ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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}`}
......
...@@ -7,6 +7,8 @@ type InputProps = { ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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 && (
......
...@@ -239,6 +239,7 @@ const ModelModal: FC<ModelModalProps> = ({ ...@@ -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> = ({ ...@@ -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}
......
...@@ -43,13 +43,13 @@ const ModelName: FC<ModelNameProps> = ({ ...@@ -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>
......
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 { ...@@ -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 ...@@ -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 = { ...@@ -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 = { ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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
? ( ? (
<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]' /> <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> = ({ ...@@ -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> = ({ ...@@ -189,14 +231,18 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
onSelect={handleChangeModel} onSelect={handleChangeModel}
/> />
</div> </div>
{
!!parameterRules.length && (
<div className='my-5 h-[1px] bg-gray-100' /> <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] : []),
......
...@@ -29,7 +29,37 @@ const ParameterItem: FC<ParameterItemProps> = ({ ...@@ -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> = ({ ...@@ -73,22 +103,8 @@ const ParameterItem: FC<ParameterItemProps> = ({
if (onSwitch) { if (onSwitch) {
let assignValue: ParameterValue = localValue let assignValue: ParameterValue = localValue
if (isNullOrUndefined(localValue)) { if (isNullOrUndefined(localValue))
if (parameterRule.type === 'int' || parameterRule.type === 'float') assignValue = getDefaultValue()
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 : []
}
onSwitch(checked, assignValue) onSwitch(checked, assignValue)
} }
...@@ -145,7 +161,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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'
/> />
......
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
...@@ -6,10 +6,10 @@ import { ...@@ -6,10 +6,10 @@ import {
ModelFeatureTextEnum, ModelFeatureTextEnum,
} from '../declarations' } from '../declarations'
import { import {
MagicBox, // MagicBox,
MagicEyes, MagicEyes,
MagicWand, // MagicWand,
Robot, // 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> = ({ ...@@ -23,41 +23,41 @@ const FeatureIcon: FC<FeatureIconProps> = ({
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
if (feature === ModelFeatureEnum.agentThought) { // if (feature === ModelFeatureEnum.agentThought) {
return ( // return (
<TooltipPlus // <TooltipPlus
popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })} // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })}
> // >
<ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
<Robot className='w-3 h-3' /> // <Robot className='w-3 h-3' />
</ModelBadge> // </ModelBadge>
</TooltipPlus> // </TooltipPlus>
) // )
} // }
if (feature === ModelFeatureEnum.toolCall) { // if (feature === ModelFeatureEnum.toolCall) {
return ( // return (
<TooltipPlus // <TooltipPlus
popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })} // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })}
> // >
<ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
<MagicWand className='w-3 h-3' /> // <MagicWand className='w-3 h-3' />
</ModelBadge> // </ModelBadge>
</TooltipPlus> // </TooltipPlus>
) // )
} // }
if (feature === ModelFeatureEnum.multiToolCall) { // if (feature === ModelFeatureEnum.multiToolCall) {
return ( // return (
<TooltipPlus // <TooltipPlus
popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })} // popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })}
> // >
<ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> // <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
<MagicBox className='w-3 h-3' /> // <MagicBox className='w-3 h-3' />
</ModelBadge> // </ModelBadge>
</TooltipPlus> // </TooltipPlus>
) // )
} // }
if (feature === ModelFeatureEnum.vision) { if (feature === ModelFeatureEnum.vision) {
return ( return (
......
...@@ -8,6 +8,7 @@ import type { ...@@ -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> = ({ ...@@ -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}
......
...@@ -3,10 +3,16 @@ import type { ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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'>
{
model.status !== ModelStatusEnum.active
? (
<TooltipPlus popupContent={MODEL_STATUS_TEXT[model.status][language]}>
<AlertTriangle className='w-4 h-4 text-[#F79009]' />
</TooltipPlus>
)
: (
<ChevronDown <ChevronDown
className='w-3.5 h-3.5 text-gray-500' className='w-3.5 h-3.5 text-gray-500'
/> />
)
}
</div> </div>
</div> </div>
) )
......
...@@ -102,7 +102,7 @@ const PopupItem: FC<PopupItemProps> = ({ ...@@ -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' />
) )
} }
......
...@@ -21,6 +21,7 @@ import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/a ...@@ -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> = ({ ...@@ -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)
......
...@@ -78,9 +78,9 @@ const ModelList: FC<ModelListProps> = ({ ...@@ -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}
......
...@@ -14,6 +14,7 @@ import { ...@@ -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> = ({ ...@@ -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')}
<TooltipPlus popupContent={
openaiOrAnthropic
? t('common.modelProvider.card.tip')
: t('common.modelProvider.quotaTip')
}>
<InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' /> <InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' />
</TooltipPlus>
</div> </div>
{ {
currentQuota && ( currentQuota && (
......
...@@ -21,6 +21,7 @@ import s from './index.module.css' ...@@ -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> = ({ ...@@ -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> = ({ ...@@ -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}
......
...@@ -43,6 +43,7 @@ import Confirm from '@/app/components/base/confirm' ...@@ -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,12 +583,30 @@ const Main: FC<IMainProps> = ({ ...@@ -582,12 +583,30 @@ const Main: FC<IMainProps> = ({
} }
setResponsingFalse() setResponsingFalse()
}, },
onMessageEnd: isInstalledApp onMessageEnd: (messageEnd) => {
? (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(
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)
return
}
// not support show citation
// responseItem.citation = messageEnd.retriever_resources
if (!isInstalledApp) if (!isInstalledApp)
return return
responseItem.citation = messageEnd.retriever_resources
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) => {
...@@ -597,8 +616,7 @@ const Main: FC<IMainProps> = ({ ...@@ -597,8 +616,7 @@ const Main: FC<IMainProps> = ({
draft.push({ ...responseItem }) draft.push({ ...responseItem })
}) })
setChatList(newListWithAnswer) setChatList(newListWithAnswer)
} },
: undefined,
onMessageReplace: (messageReplace) => { onMessageReplace: (messageReplace) => {
if (isInstalledApp) { if (isInstalledApp) {
responseItem.content = messageReplace.answer responseItem.content = messageReplace.answer
...@@ -615,22 +633,6 @@ const Main: FC<IMainProps> = ({ ...@@ -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
......
...@@ -300,6 +300,9 @@ const translation = { ...@@ -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',
......
...@@ -300,6 +300,9 @@ const translation = { ...@@ -300,6 +300,9 @@ const translation = {
buyQuota: '购买额度', buyQuota: '购买额度',
getFreeTokens: '获得免费 Tokens', getFreeTokens: '获得免费 Tokens',
priorityUsing: '优先使用', priorityUsing: '优先使用',
deprecated: '已弃用',
confirmDelete: '确认删除?',
quotaTip: '剩余免费额度',
}, },
dataSource: { dataSource: {
add: '添加数据源', add: '添加数据源',
......
...@@ -47,7 +47,6 @@ type IOtherOptions = { ...@@ -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) { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 })
......
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 = { ...@@ -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>, ...@@ -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) => {
......
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) { ...@@ -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 ...@@ -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 = '') => {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment