Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
c06e766d
Unverified
Commit
c06e766d
authored
Jan 04, 2024
by
zxhlyh
Committed by
GitHub
Jan 04, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: model parameter prefefined (#1917)
parent
4a3d15b6
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
100 additions
and
592 deletions
+100
-592
index.tsx
web/app/components/app/configuration/config-model/index.tsx
+0
-423
model-mode-type-label.tsx
.../app/configuration/config-model/model-mode-type-label.tsx
+0
-29
model-name.tsx
.../components/app/configuration/config-model/model-name.tsx
+0
-26
param-item.tsx
.../components/app/configuration/config-model/param-item.tsx
+0
-95
provider-name.tsx
...mponents/app/configuration/config-model/provider-name.tsx
+0
-18
index.tsx
web/app/components/app/configuration/index.tsx
+0
-1
index.tsx
...tting/model-provider-page/model-parameter-modal/index.tsx
+100
-0
No files found.
web/app/components/app/configuration/config-model/index.tsx
deleted
100644 → 0
View file @
4a3d15b6
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
cn
from
'classnames'
import
{
useTranslation
}
from
'react-i18next'
import
{
useBoolean
,
useClickAway
,
useGetState
}
from
'ahooks'
import
{
InformationCircleIcon
}
from
'@heroicons/react/24/outline'
import
produce
from
'immer'
import
ParamItem
from
'./param-item'
import
{
SlidersH
}
from
'@/app/components/base/icons/src/vender/line/mediaAndDevices'
import
Radio
from
'@/app/components/base/radio'
import
Panel
from
'@/app/components/base/panel'
import
type
{
CompletionParams
}
from
'@/models/debug'
import
{
TONE_LIST
}
from
'@/config'
import
Toast
from
'@/app/components/base/toast'
import
{
AlertTriangle
}
from
'@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
import
{
formatNumber
}
from
'@/utils/format'
import
{
Brush01
}
from
'@/app/components/base/icons/src/vender/solid/editor'
import
{
Scales02
}
from
'@/app/components/base/icons/src/vender/solid/FinanceAndECommerce'
import
{
Target04
}
from
'@/app/components/base/icons/src/vender/solid/general'
import
{
Sliders02
}
from
'@/app/components/base/icons/src/vender/solid/mediaAndDevices'
import
{
fetchModelParams
}
from
'@/service/debug'
import
Loading
from
'@/app/components/base/loading'
import
useBreakpoints
,
{
MediaType
}
from
'@/hooks/use-breakpoints'
import
type
{
ModelModeType
}
from
'@/types/app'
import
ModelIcon
from
'@/app/components/header/account-setting/model-provider-page/model-icon'
import
ModelName
from
'@/app/components/header/account-setting/model-provider-page/model-name'
import
ModelSelector
from
'@/app/components/header/account-setting/model-provider-page/model-selector'
import
{
useTextGenerationCurrentProviderAndModelAndModelList
}
from
'@/app/components/header/account-setting/model-provider-page/hooks'
export
type
IConfigModelProps
=
{
isAdvancedMode
:
boolean
mode
:
string
modelId
:
string
provider
:
string
setModel
:
(
model
:
{
id
:
string
;
provider
:
string
;
mode
:
ModelModeType
;
features
:
string
[]
})
=>
void
completionParams
:
CompletionParams
onCompletionParamsChange
:
(
newParams
:
CompletionParams
)
=>
void
disabled
:
boolean
}
const
ConfigModel
:
FC
<
IConfigModelProps
>
=
({
isAdvancedMode
,
modelId
,
provider
,
setModel
,
completionParams
,
onCompletionParamsChange
,
disabled
,
})
=>
{
const
{
t
}
=
useTranslation
()
const
[
isShowConfig
,
{
setFalse
:
hideConfig
,
toggle
:
toogleShowConfig
}]
=
useBoolean
(
false
)
const
[
maxTokenSettingTipVisible
,
setMaxTokenSettingTipVisible
]
=
useState
(
false
)
const
configContentRef
=
React
.
useRef
(
null
)
const
{
currentProvider
,
currentModel
:
currModel
,
textGenerationModelList
,
}
=
useTextGenerationCurrentProviderAndModelAndModelList
(
{
provider
,
model
:
modelId
},
)
const
media
=
useBreakpoints
()
const
isMobile
=
media
===
MediaType
.
mobile
// Cache loaded model param
const
[
allParams
,
setAllParams
,
getAllParams
]
=
useGetState
<
Record
<
string
,
Record
<
string
,
any
>>>
({})
const
currParams
=
allParams
[
provider
]?.[
modelId
]
const
hasEnableParams
=
currParams
&&
Object
.
keys
(
currParams
).
some
(
key
=>
currParams
[
key
].
enabled
)
const
allSupportParams
=
[
'temperature'
,
'top_p'
,
'presence_penalty'
,
'frequency_penalty'
,
'max_tokens'
]
const
currSupportParams
=
currParams
?
allSupportParams
.
filter
(
key
=>
currParams
[
key
].
enabled
)
:
allSupportParams
if
(
isAdvancedMode
)
currSupportParams
.
push
(
'stop'
)
useEffect
(()
=>
{
(
async
()
=>
{
if
(
!
allParams
[
provider
]?.[
modelId
])
{
const
res
=
await
fetchModelParams
(
provider
,
modelId
)
const
newAllParams
=
produce
(
allParams
,
(
draft
)
=>
{
if
(
!
draft
[
provider
])
draft
[
provider
]
=
{}
draft
[
provider
][
modelId
]
=
res
})
setAllParams
(
newAllParams
)
}
})()
},
[
provider
,
modelId
,
allParams
,
setAllParams
])
useClickAway
(()
=>
{
hideConfig
()
},
configContentRef
)
const
selectedModel
=
{
name
:
modelId
}
// options.find(option => option.id === modelId)
const
ensureModelParamLoaded
=
(
provider
:
string
,
modelId
:
string
)
=>
{
return
new
Promise
<
void
>
((
resolve
)
=>
{
if
(
getAllParams
()[
provider
]?.[
modelId
])
{
resolve
()
return
}
const
runId
=
setInterval
(()
=>
{
if
(
getAllParams
()[
provider
]?.[
modelId
])
{
resolve
()
clearInterval
(
runId
)
}
},
500
)
})
}
const
transformValue
=
(
value
:
number
,
fromRange
:
[
number
,
number
],
toRange
:
[
number
,
number
]):
number
=>
{
const
[
fromStart
=
0
,
fromEnd
]
=
fromRange
const
[
toStart
=
0
,
toEnd
]
=
toRange
// The following three if is to avoid precision loss
if
(
fromStart
===
toStart
&&
fromEnd
===
toEnd
)
return
value
if
(
value
<=
fromStart
)
return
toStart
if
(
value
>=
fromEnd
)
return
toEnd
const
fromLength
=
fromEnd
-
fromStart
const
toLength
=
toEnd
-
toStart
let
adjustedValue
=
(
value
-
fromStart
)
*
(
toLength
/
fromLength
)
+
toStart
adjustedValue
=
parseFloat
(
adjustedValue
.
toFixed
(
2
))
return
adjustedValue
}
const
handleSelectModel
=
({
id
,
provider
:
nextProvider
,
mode
,
features
}:
{
id
:
string
;
provider
:
string
;
mode
:
ModelModeType
;
features
:
string
[]
})
=>
{
return
async
()
=>
{
const
prevParamsRule
=
getAllParams
()[
provider
]?.[
modelId
]
setModel
({
id
,
provider
:
nextProvider
||
'openai'
,
mode
,
features
,
})
await
ensureModelParamLoaded
(
nextProvider
,
id
)
const
nextParamsRule
=
getAllParams
()[
nextProvider
]?.[
id
]
// debugger
const
nextSelectModelMaxToken
=
nextParamsRule
.
max_tokens
.
max
const
newConCompletionParams
=
produce
(
completionParams
,
(
draft
:
any
)
=>
{
if
(
nextParamsRule
.
max_tokens
.
enabled
)
{
if
(
completionParams
.
max_tokens
>
nextSelectModelMaxToken
)
{
Toast
.
notify
({
type
:
'warning'
,
message
:
t
(
'common.model.params.setToCurrentModelMaxTokenTip'
,
{
maxToken
:
formatNumber
(
nextSelectModelMaxToken
)
}),
})
draft
.
max_tokens
=
parseFloat
((
nextSelectModelMaxToken
*
0.8
).
toFixed
(
2
))
}
// prev don't have max token
if
(
!
completionParams
.
max_tokens
)
draft
.
max_tokens
=
nextParamsRule
.
max_tokens
.
default
}
else
{
delete
draft
.
max_tokens
}
allSupportParams
.
forEach
((
key
)
=>
{
if
(
key
===
'max_tokens'
)
return
if
(
!
nextParamsRule
[
key
].
enabled
)
{
delete
draft
[
key
]
return
}
if
(
draft
[
key
]
===
undefined
)
{
draft
[
key
]
=
nextParamsRule
[
key
].
default
||
0
return
}
if
(
!
prevParamsRule
[
key
].
enabled
)
{
draft
[
key
]
=
nextParamsRule
[
key
].
default
||
0
return
}
draft
[
key
]
=
transformValue
(
draft
[
key
],
[
prevParamsRule
[
key
].
min
,
prevParamsRule
[
key
].
max
],
[
nextParamsRule
[
key
].
min
,
nextParamsRule
[
key
].
max
],
)
})
})
onCompletionParamsChange
(
newConCompletionParams
)
}
}
// only openai support this
function
matchToneId
(
completionParams
:
CompletionParams
):
number
{
const
remvoedCustomeTone
=
TONE_LIST
.
slice
(
0
,
-
1
)
const
CUSTOM_TONE_ID
=
4
const
tone
=
remvoedCustomeTone
.
find
((
tone
)
=>
{
return
tone
.
config
?.
temperature
===
completionParams
.
temperature
&&
tone
.
config
?.
top_p
===
completionParams
.
top_p
&&
tone
.
config
?.
presence_penalty
===
completionParams
.
presence_penalty
&&
tone
.
config
?.
frequency_penalty
===
completionParams
.
frequency_penalty
})
return
tone
?
tone
.
id
:
CUSTOM_TONE_ID
}
// tone is a preset of completionParams.
const
[
toneId
,
setToneId
]
=
React
.
useState
(
matchToneId
(
completionParams
))
// default is Balanced
const
toneTabBgClassName
=
({
1
:
'bg-[#F5F8FF]'
,
2
:
'bg-[#F4F3FF]'
,
3
:
'bg-[#F6FEFC]'
,
})[
toneId
]
||
''
// set completionParams by toneId
const
handleToneChange
=
(
id
:
number
)
=>
{
if
(
id
===
4
)
return
// custom tone
const
tone
=
TONE_LIST
.
find
(
tone
=>
tone
.
id
===
id
)
if
(
tone
)
{
setToneId
(
id
)
onCompletionParamsChange
({
...
tone
.
config
,
max_tokens
:
completionParams
.
max_tokens
,
}
as
CompletionParams
)
}
}
useEffect
(()
=>
{
setToneId
(
matchToneId
(
completionParams
))
},
[
completionParams
])
const
handleParamChange
=
(
key
:
string
,
value
:
number
|
string
[])
=>
{
if
(
value
===
undefined
)
return
if
((
completionParams
as
any
)[
key
]
===
value
)
return
if
(
key
===
'stop'
)
{
onCompletionParamsChange
({
...
completionParams
,
[
key
]:
value
as
string
[],
})
}
else
{
const
currParamsRule
=
getAllParams
()[
provider
]?.[
modelId
]
let
notOutRangeValue
=
parseFloat
((
value
as
number
).
toFixed
(
2
))
notOutRangeValue
=
Math
.
max
(
currParamsRule
[
key
].
min
,
notOutRangeValue
)
notOutRangeValue
=
Math
.
min
(
currParamsRule
[
key
].
max
,
notOutRangeValue
)
onCompletionParamsChange
({
...
completionParams
,
[
key
]:
notOutRangeValue
,
})
}
}
const
ableStyle
=
'bg-indigo-25 border-[#2A87F5] cursor-pointer'
const
diabledStyle
=
'bg-[#FFFCF5] border-[#F79009]'
const
getToneIcon
=
(
toneId
:
number
)
=>
{
const
className
=
'w-[14px] h-[14px]'
const
res
=
({
1
:
<
Brush01
className
=
{
className
}
/>
,
2
:
<
Scales02
className
=
{
className
}
/>
,
3
:
<
Target04
className
=
{
className
}
/>
,
4
:
<
Sliders02
className
=
{
className
}
/>
,
})[
toneId
]
return
res
}
useEffect
(()
=>
{
if
(
!
currParams
)
return
const
max
=
currParams
.
max_tokens
.
max
const
isSupportMaxToken
=
currParams
.
max_tokens
.
enabled
if
(
isSupportMaxToken
&&
currentProvider
?.
provider
!==
'anthropic'
&&
completionParams
.
max_tokens
>
max
*
2
/
3
)
setMaxTokenSettingTipVisible
(
true
)
else
setMaxTokenSettingTipVisible
(
false
)
},
[
currParams
,
completionParams
.
max_tokens
,
setMaxTokenSettingTipVisible
,
currentProvider
])
return
(
<
div
className=
'relative'
ref=
{
configContentRef
}
>
<
div
className=
{
cn
(
'flex items-center border h-8 px-2 space-x-2 rounded-lg'
,
disabled
?
diabledStyle
:
ableStyle
)
}
onClick=
{
()
=>
!
disabled
&&
toogleShowConfig
()
}
>
{
currentProvider
&&
(
<
ModelIcon
className=
'!w-5 !h-5'
provider=
{
currentProvider
}
/>
)
}
{
currModel
&&
(
<
ModelName
className=
'text-gray-900'
modelItem=
{
currModel
}
showMode=
{
isAdvancedMode
}
/>
)
}
{
disabled
?
<
InformationCircleIcon
className=
'w-4 h-4 text-[#F79009]'
/>
:
<
SlidersH
className=
'w-4 h-4 text-indigo-600'
/>
}
</
div
>
{
isShowConfig
&&
(
<
Panel
className=
'absolute z-20 top-8 left-0 sm:left-[unset] sm:right-0 !w-fit sm:!w-[496px] bg-white !overflow-visible shadow-md'
keepUnFold
headerIcon=
{
<
svg
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<
path
d=
"M8.26865 0.790031C8.09143 0.753584 7.90866 0.753584 7.73144 0.790031C7.52659 0.832162 7.3435 0.934713 7.19794 1.01624L7.15826 1.03841L6.17628 1.58395C5.85443 1.76276 5.73846 2.16863 5.91727 2.49049C6.09608 2.81234 6.50195 2.9283 6.82381 2.74949L7.80579 2.20395C7.90681 2.14782 7.95839 2.11946 7.99686 2.10091L8.00004 2.09938L8.00323 2.10091C8.0417 2.11946 8.09327 2.14782 8.1943 2.20395L9.17628 2.74949C9.49814 2.9283 9.90401 2.81234 10.0828 2.49048C10.2616 2.16863 10.1457 1.76276 9.82381 1.58395L8.84183 1.03841L8.80215 1.01624C8.65659 0.934713 8.4735 0.832162 8.26865 0.790031Z"
fill=
"#1C64F2"
/>
<
path
d=
"M12.8238 3.25062C12.5019 3.07181 12.0961 3.18777 11.9173 3.50963C11.7385 3.83148 11.8544 4.23735 12.1763 4.41616L12.6272 4.66668L12.1763 4.91719C11.8545 5.096 11.7385 5.50186 11.9173 5.82372C12.0961 6.14558 12.502 6.26154 12.8238 6.08273L13.3334 5.79966V6.33339C13.3334 6.70158 13.6319 7.00006 14 7.00006C14.3682 7.00006 14.6667 6.70158 14.6667 6.33339V5.29435L14.6668 5.24627C14.6673 5.12441 14.6678 4.98084 14.6452 4.83482C14.6869 4.67472 14.6696 4.49892 14.5829 4.34286C14.4904 4.1764 14.3371 4.06501 14.1662 4.02099C14.0496 3.93038 13.9239 3.86116 13.8173 3.8024L13.7752 3.77915L12.8238 3.25062Z"
fill=
"#1C64F2"
/>
<
path
d=
"M3.8238 4.41616C4.14566 4.23735 4.26162 3.83148 4.08281 3.50963C3.90401 3.18777 3.49814 3.07181 3.17628 3.25062L2.22493 3.77915L2.18284 3.8024C2.07615 3.86116 1.95045 3.9304 1.83382 4.02102C1.66295 4.06506 1.50977 4.17643 1.41731 4.34286C1.33065 4.49886 1.31323 4.67459 1.35493 4.83464C1.33229 4.98072 1.33281 5.12436 1.33326 5.24627L1.33338 5.29435V6.33339C1.33338 6.70158 1.63185 7.00006 2.00004 7.00006C2.36823 7.00006 2.66671 6.70158 2.66671 6.33339V5.79961L3.17632 6.08273C3.49817 6.26154 3.90404 6.14558 4.08285 5.82372C4.26166 5.50186 4.1457 5.096 3.82384 4.91719L3.3729 4.66666L3.8238 4.41616Z"
fill=
"#1C64F2"
/>
<
path
d=
"M2.66671 9.66672C2.66671 9.29853 2.36823 9.00006 2.00004 9.00006C1.63185 9.00006 1.33338 9.29853 1.33338 9.66672V10.7058L1.33326 10.7538C1.33262 10.9298 1.33181 11.1509 1.40069 11.3594C1.46024 11.5397 1.55759 11.7051 1.68622 11.8447C1.835 12.0061 2.02873 12.1128 2.18281 12.1977L2.22493 12.221L3.17628 12.7495C3.49814 12.9283 3.90401 12.8123 4.08281 12.4905C4.26162 12.1686 4.14566 11.7628 3.8238 11.584L2.87245 11.0554C2.76582 10.9962 2.71137 10.9656 2.67318 10.9413L2.66995 10.9392L2.66971 10.9354C2.66699 10.8902 2.66671 10.8277 2.66671 10.7058V9.66672Z"
fill=
"#1C64F2"
/>
<
path
d=
"M14.6667 9.66672C14.6667 9.29853 14.3682 9.00006 14 9.00006C13.6319 9.00006 13.3334 9.29853 13.3334 9.66672V10.7058C13.3334 10.8277 13.3331 10.8902 13.3304 10.9354L13.3301 10.9392L13.3269 10.9413C13.2887 10.9656 13.2343 10.9962 13.1276 11.0554L12.1763 11.584C11.8544 11.7628 11.7385 12.1686 11.9173 12.4905C12.0961 12.8123 12.5019 12.9283 12.8238 12.7495L13.7752 12.221L13.8172 12.1977C13.9713 12.1128 14.1651 12.0061 14.3139 11.8447C14.4425 11.7051 14.5398 11.5397 14.5994 11.3594C14.6683 11.1509 14.6675 10.9298 14.6668 10.7538L14.6667 10.7058V9.66672Z"
fill=
"#1C64F2"
/>
<
path
d=
"M6.82381 13.2506C6.50195 13.0718 6.09608 13.1878 5.91727 13.5096C5.73846 13.8315 5.85443 14.2374 6.17628 14.4162L7.15826 14.9617L7.19793 14.9839C7.29819 15.04 7.41625 15.1061 7.54696 15.1556C7.66589 15.2659 7.82512 15.3333 8.00008 15.3333C8.17507 15.3333 8.33431 15.2659 8.45324 15.1556C8.58391 15.1061 8.70193 15.04 8.80215 14.9839L8.84183 14.9617L9.82381 14.4162C10.1457 14.2374 10.2616 13.8315 10.0828 13.5096C9.90401 13.1878 9.49814 13.0718 9.17628 13.2506L8.66675 13.5337V13C8.66675 12.6318 8.36827 12.3333 8.00008 12.3333C7.63189 12.3333 7.33341 12.6318 7.33341 13V13.5337L6.82381 13.2506Z"
fill=
"#1C64F2"
/>
<
path
d=
"M6.82384 6.58385C6.50199 6.40505 6.09612 6.52101 5.91731 6.84286C5.7385 7.16472 5.85446 7.57059 6.17632 7.7494L7.33341 8.39223V9.66663C7.33341 10.0348 7.63189 10.3333 8.00008 10.3333C8.36827 10.3333 8.66675 10.0348 8.66675 9.66663V8.39223L9.82384 7.7494C10.1457 7.57059 10.2617 7.16472 10.0829 6.84286C9.90404 6.52101 9.49817 6.40505 9.17632 6.58385L8.00008 7.23732L6.82384 6.58385Z"
fill=
"#1C64F2"
/>
</
svg
>
}
title=
{
t
(
'appDebug.modelConfig.title'
)
}
>
<
div
className=
'py-3 pl-10 pr-6 text-sm'
>
<
div
className=
"flex items-center justify-between my-5 h-9"
>
<
div
>
{
t
(
'appDebug.modelConfig.model'
)
}
</
div
>
<
ModelSelector
defaultModel=
{
{
model
:
modelId
,
provider
}
}
modelList=
{
textGenerationModelList
}
onSelect=
{
({
provider
,
model
})
=>
{
const
targetProvider
=
textGenerationModelList
.
find
(
modelItem
=>
modelItem
.
provider
===
provider
)
const
targetModelItem
=
targetProvider
?.
models
.
find
(
modelItem
=>
modelItem
.
model
===
model
)
handleSelectModel
({
id
:
model
,
provider
,
mode
:
targetModelItem
?.
model_properties
.
mode
as
ModelModeType
,
features
:
targetModelItem
?.
features
||
[],
})()
}
}
/>
</
div
>
{
hasEnableParams
&&
(
<
div
className=
"border-b border-gray-100"
></
div
>
)
}
{
/* Tone type */
}
{
[
'openai'
,
'azure_openai'
].
includes
(
provider
)
&&
(
<
div
className=
"mt-5 mb-4"
>
<
div
className=
"mb-3 text-sm text-gray-900"
>
{
t
(
'appDebug.modelConfig.setTone'
)
}
</
div
>
<
Radio
.
Group
className=
{
cn
(
'!rounded-lg'
,
toneTabBgClassName
)
}
value=
{
toneId
}
onChange=
{
handleToneChange
}
>
<>
{
TONE_LIST
.
slice
(
0
,
3
).
map
(
tone
=>
(
<
div
className=
'grow flex items-center'
key=
{
tone
.
id
}
>
<
Radio
value=
{
tone
.
id
}
className=
{
cn
(
tone
.
id
===
toneId
&&
'rounded-md border border-gray-200 shadow-md'
,
'!mr-0 grow !px-1 sm:!px-2 !justify-center text-[13px] font-medium'
)
}
labelClassName=
{
cn
(
tone
.
id
===
toneId
?
({
1
:
'text-[#6938EF]'
,
2
:
'text-[#444CE7]'
,
3
:
'text-[#107569]'
,
})[
toneId
]
:
'text-[#667085]'
,
'flex items-center space-x-2'
)
}
>
<>
{
getToneIcon
(
tone
.
id
)
}
{
!
isMobile
&&
<
div
>
{
t
(
`common.model.tone.${tone.name}`
)
as
string
}
</
div
>
}
<
div
className=
""
></
div
>
</>
</
Radio
>
{
tone
.
id
!==
toneId
&&
tone
.
id
+
1
!==
toneId
&&
(<
div
className=
'h-5 border-r border-gray-200'
></
div
>)
}
</
div
>
))
}
</>
<
Radio
value=
{
TONE_LIST
[
3
].
id
}
className=
{
cn
(
toneId
===
4
&&
'rounded-md border border-gray-200 shadow-md'
,
'!mr-0 grow !px-1 sm:!px-2 !justify-center text-[13px] font-medium'
)
}
labelClassName=
{
cn
(
'flex items-center space-x-2 '
,
toneId
===
4
?
'text-[#155EEF]'
:
'text-[#667085]'
)
}
>
<>
{
getToneIcon
(
TONE_LIST
[
3
].
id
)
}
{
!
isMobile
&&
<
div
>
{
t
(
`common.model.tone.${TONE_LIST[3].name}`
)
as
string
}
</
div
>
}
</>
</
Radio
>
</
Radio
.
Group
>
</
div
>
)
}
{
/* Params */
}
<
div
className=
{
cn
(
hasEnableParams
&&
'mt-4'
,
'space-y-4'
,
!
allParams
[
provider
]?.[
modelId
]
&&
'flex items-center min-h-[200px]'
)
}
>
{
(
allParams
[
provider
]?.[
modelId
])
?
(
currSupportParams
.
map
(
key
=>
(<
ParamItem
key=
{
key
}
id=
{
key
}
name=
{
t
(
`common.model.params.${key === 'stop' ? 'stop_sequences' : key}`
)
}
tip=
{
t
(
`common.model.params.${key === 'stop' ? 'stop_sequences' : key}Tip`
)
}
{
...
currParams
[
key
]
as
any
}
value=
{
(
completionParams
as
any
)[
key
]
as
any
}
onChange=
{
handleParamChange
}
inputType=
{
key
===
'stop'
?
'inputTag'
:
'slider'
}
/>))
)
:
(
<
Loading
type=
'area'
/>
)
}
</
div
>
</
div
>
{
maxTokenSettingTipVisible
&&
(
<
div
className=
'flex py-2 pr-4 pl-5 rounded-bl-xl rounded-br-xl bg-[#FFFAEB] border-t border-[#FEF0C7]'
>
<
AlertTriangle
className=
'shrink-0 mr-2 mt-[3px] w-3 h-3 text-[#F79009]'
/>
<
div
className=
'mr-2 text-xs font-medium text-gray-700'
>
{
t
(
'common.model.params.maxTokenSettingTip'
)
}
</
div
>
</
div
>
)
}
</
Panel
>
)
}
</
div
>
)
}
export
default
React
.
memo
(
ConfigModel
)
web/app/components/app/configuration/config-model/model-mode-type-label.tsx
deleted
100644 → 0
View file @
4a3d15b6
'use client'
import
type
{
FC
}
from
'react'
import
React
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
type
{
ModelModeType
}
from
'@/types/app'
type
Props
=
{
className
?:
string
type
:
ModelModeType
isHighlight
?:
boolean
}
const
ModelModeTypeLabel
:
FC
<
Props
>
=
({
className
,
type
,
isHighlight
,
})
=>
{
const
{
t
}
=
useTranslation
()
return
(
<
div
className=
{
cn
(
className
,
isHighlight
?
'border-indigo-300 text-indigo-600'
:
'border-gray-300 text-gray-500'
,
'flex items-center h-4 px-1 border rounded text-xs font-semibold uppercase text-ellipsis overflow-hidden whitespace-nowrap'
)
}
>
{
t
(
`appDebug.modelConfig.modeType.${type}`
)
}
</
div
>
)
}
export
default
React
.
memo
(
ModelModeTypeLabel
)
web/app/components/app/configuration/config-model/model-name.tsx
deleted
100644 → 0
View file @
4a3d15b6
'use client'
import
type
{
FC
}
from
'react'
import
React
from
'react'
export
type
IModelNameProps
=
{
modelId
:
string
modelDisplayName
?:
string
}
export
const
supportI18nModelName
=
[
'gpt-3.5-turbo'
,
'gpt-3.5-turbo-16k'
,
'gpt-4'
,
'gpt-4-32k'
,
'text-davinci-003'
,
'text-embedding-ada-002'
,
'whisper-1'
,
'claude-instant-1'
,
'claude-2'
,
]
const
ModelName
:
FC
<
IModelNameProps
>
=
({
modelDisplayName
,
})
=>
{
return
(
<
span
className=
'text-ellipsis overflow-hidden whitespace-nowrap'
title=
{
modelDisplayName
}
>
{
modelDisplayName
}
</
span
>
)
}
export
default
React
.
memo
(
ModelName
)
web/app/components/app/configuration/config-model/param-item.tsx
deleted
100644 → 0
View file @
4a3d15b6
'use client'
import
type
{
FC
}
from
'react'
import
React
,
{
useEffect
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
Tooltip
from
'@/app/components/base/tooltip'
import
Slider
from
'@/app/components/base/slider'
import
TagInput
from
'@/app/components/base/tag-input'
export
const
getFitPrecisionValue
=
(
num
:
number
,
precision
:
number
|
null
)
=>
{
if
(
!
precision
||
!
(
`
${
num
}
`
).
includes
(
'.'
))
return
num
const
currNumPrecision
=
(
`
${
num
}
`
).
split
(
'.'
)[
1
].
length
if
(
currNumPrecision
>
precision
)
return
parseFloat
(
num
.
toFixed
(
precision
))
return
num
}
export
type
IParamIteProps
=
{
id
:
string
name
:
string
tip
:
string
value
:
number
|
string
[]
step
?:
number
min
?:
number
max
:
number
precision
:
number
|
null
onChange
:
(
key
:
string
,
value
:
number
|
string
[])
=>
void
inputType
?:
'inputTag'
|
'slider'
}
const
TIMES_TEMPLATE
=
'1000000000000'
const
ParamItem
:
FC
<
IParamIteProps
>
=
({
id
,
name
,
tip
,
step
=
0.1
,
min
=
0
,
max
,
precision
,
value
,
inputType
,
onChange
})
=>
{
const
{
t
}
=
useTranslation
()
const
getToIntTimes
=
(
num
:
number
)
=>
{
if
(
precision
)
return
parseInt
(
TIMES_TEMPLATE
.
slice
(
0
,
precision
+
1
),
10
)
if
(
num
<
5
)
return
10
return
1
}
const
times
=
getToIntTimes
(
max
)
useEffect
(()
=>
{
if
(
precision
)
onChange
(
id
,
getFitPrecisionValue
(
value
,
precision
))
},
[
value
,
precision
])
return
(
<
div
className=
"flex items-center justify-between flex-wrap gap-y-2"
>
<
div
className=
"flex flex-col flex-shrink-0"
>
<
div
className=
"flex items-center"
>
<
span
className=
"mr-[6px] text-gray-500 text-[13px] font-medium"
>
{
name
}
</
span
>
{
/* Give tooltip different tip to avoiding hide bug */
}
<
Tooltip
htmlContent=
{
<
div
className=
"w-[200px] whitespace-pre-wrap"
>
{
tip
}
</
div
>
}
position=
'top'
selector=
{
`param-name-tooltip-${id}`
}
>
<
svg
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<
path
d=
"M8.66667 10.6667H8V8H7.33333M8 5.33333H8.00667M14 8C14 8.78793 13.8448 9.56815 13.5433 10.2961C13.2417 11.0241 12.7998 11.6855 12.2426 12.2426C11.6855 12.7998 11.0241 13.2417 10.2961 13.5433C9.56815 13.8448 8.78793 14 8 14C7.21207 14 6.43185 13.8448 5.7039 13.5433C4.97595 13.2417 4.31451 12.7998 3.75736 12.2426C3.20021 11.6855 2.75825 11.0241 2.45672 10.2961C2.15519 9.56815 2 8.78793 2 8C2 6.4087 2.63214 4.88258 3.75736 3.75736C4.88258 2.63214 6.4087 2 8 2C9.5913 2 11.1174 2.63214 12.2426 3.75736C13.3679 4.88258 14 6.4087 14 8Z"
stroke=
"#9CA3AF"
strokeWidth=
"1.5"
strokeLinecap=
"round"
strokeLinejoin=
"round"
/>
</
svg
>
</
Tooltip
>
</
div
>
{
inputType
===
'inputTag'
&&
<
div
className=
"text-gray-400 text-xs font-normal"
>
{
t
(
'common.model.params.stop_sequencesPlaceholder'
)
}
</
div
>
}
</
div
>
<
div
className=
"flex items-center"
>
{
inputType
===
'inputTag'
?
<
TagInput
items=
{
(
value
??
[])
as
string
[]
}
onChange=
{
newSequences
=>
onChange
(
id
,
newSequences
)
}
customizedConfirmKey=
'Tab'
/>
:
(
<>
<
div
className=
"mr-4 w-[120px]"
>
<
Slider
value=
{
value
*
times
}
min=
{
min
*
times
}
max=
{
max
*
times
}
onChange=
{
(
value
)
=>
{
onChange
(
id
,
value
/
times
)
}
}
/>
</
div
>
<
input
type=
"number"
min=
{
min
}
max=
{
max
}
step=
{
step
}
className=
"block w-[64px] h-9 leading-9 rounded-lg border-0 pl-1 pl py-1.5 bg-gray-50 text-gray-900 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-primary-600"
value=
{
value
}
onChange=
{
(
e
)
=>
{
let
value
=
getFitPrecisionValue
(
isNaN
(
parseFloat
(
e
.
target
.
value
))
?
min
:
parseFloat
(
e
.
target
.
value
),
precision
)
if
(
value
<
min
)
value
=
min
if
(
value
>
max
)
value
=
max
onChange
(
id
,
value
)
}
}
/>
</>
)
}
</
div
>
</
div
>
)
}
export
default
React
.
memo
(
ParamItem
)
web/app/components/app/configuration/config-model/provider-name.tsx
deleted
100644 → 0
View file @
4a3d15b6
'use client'
import
type
{
FC
}
from
'react'
import
React
from
'react'
export
type
IProviderNameProps
=
{
provideName
:
string
}
const
ProviderName
:
FC
<
IProviderNameProps
>
=
({
provideName
,
})
=>
{
return
(
<
span
>
{
provideName
}
</
span
>
)
}
export
default
React
.
memo
(
ProviderName
)
web/app/components/app/configuration/index.tsx
View file @
c06e766d
...
...
@@ -28,7 +28,6 @@ import type { ExternalDataTool } from '@/models/common'
import
type
{
DataSet
}
from
'@/models/datasets'
import
type
{
ModelConfig
as
BackendModelConfig
,
VisionSettings
}
from
'@/types/app'
import
ConfigContext
from
'@/context/debug-configuration'
// import ConfigModel from '@/app/components/app/configuration/config-model'
import
Config
from
'@/app/components/app/configuration/config'
import
Debug
from
'@/app/components/app/configuration/debug'
import
Confirm
from
'@/app/components/base/confirm'
...
...
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx
View file @
c06e766d
import
type
{
FC
}
from
'react'
import
{
useEffect
,
useMemo
,
useState
}
from
'react'
import
useSWR
from
'swr'
import
cn
from
'classnames'
import
{
useTranslation
}
from
'react-i18next'
import
type
{
DefaultModel
,
...
...
@@ -32,6 +33,13 @@ import { fetchModelParameterRules } from '@/service/common'
import
Loading
from
'@/app/components/base/loading'
import
{
useProviderContext
}
from
'@/context/provider-context'
import
TooltipPlus
from
'@/app/components/base/tooltip-plus'
import
Radio
from
'@/app/components/base/radio'
import
{
TONE_LIST
}
from
'@/config'
import
{
Brush01
}
from
'@/app/components/base/icons/src/vender/solid/editor'
import
{
Scales02
}
from
'@/app/components/base/icons/src/vender/solid/FinanceAndECommerce'
import
{
Target04
}
from
'@/app/components/base/icons/src/vender/solid/general'
import
{
Sliders02
}
from
'@/app/components/base/icons/src/vender/solid/mediaAndDevices'
import
useBreakpoints
,
{
MediaType
}
from
'@/hooks/use-breakpoints'
type
ModelParameterModalProps
=
{
isAdvancedMode
:
boolean
...
...
@@ -71,6 +79,8 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
const
{
t
}
=
useTranslation
()
const
language
=
useLanguage
()
const
{
hasSettedApiKey
,
modelProviders
}
=
useProviderContext
()
const
media
=
useBreakpoints
()
const
isMobile
=
media
===
MediaType
.
mobile
const
[
open
,
setOpen
]
=
useState
(
false
)
const
{
data
:
parameterRulesData
,
isLoading
}
=
useSWR
(
`/workspaces/current/model-providers/
${
provider
}
/models/parameter-rules?model=
${
modelId
}
`
,
fetchModelParameterRules
)
const
{
...
...
@@ -89,6 +99,44 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
return
parameterRulesData
?.
data
||
[]
},
[
parameterRulesData
])
// only openai support this
function
matchToneId
(
completionParams
:
FormValue
):
number
{
const
remvoedCustomeTone
=
TONE_LIST
.
slice
(
0
,
-
1
)
const
CUSTOM_TONE_ID
=
4
const
tone
=
remvoedCustomeTone
.
find
((
tone
)
=>
{
return
tone
.
config
?.
temperature
===
completionParams
.
temperature
&&
tone
.
config
?.
top_p
===
completionParams
.
top_p
&&
tone
.
config
?.
presence_penalty
===
completionParams
.
presence_penalty
&&
tone
.
config
?.
frequency_penalty
===
completionParams
.
frequency_penalty
})
return
tone
?
tone
.
id
:
CUSTOM_TONE_ID
}
// tone is a preset of completionParams.
const
[
toneId
,
setToneId
]
=
useState
(
matchToneId
(
completionParams
))
// default is Balanced
const
toneTabBgClassName
=
({
1
:
'bg-[#F5F8FF]'
,
2
:
'bg-[#F4F3FF]'
,
3
:
'bg-[#F6FEFC]'
,
})[
toneId
]
||
''
// set completionParams by toneId
const
handleToneChange
=
(
id
:
number
)
=>
{
if
(
id
===
4
)
return
// custom tone
const
tone
=
TONE_LIST
.
find
(
tone
=>
tone
.
id
===
id
)
if
(
tone
)
{
setToneId
(
id
)
onCompletionParamsChange
({
...
tone
.
config
,
max_tokens
:
completionParams
.
max_tokens
,
})
}
}
useEffect
(()
=>
{
setToneId
(
matchToneId
(
completionParams
))
},
[
completionParams
])
const
handleParamChange
=
(
key
:
string
,
value
:
ParameterValue
)
=>
{
onCompletionParamsChange
({
...
completionParams
,
...
...
@@ -138,6 +186,17 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
handleInitialParams
()
},
[
parameterRules
])
const
getToneIcon
=
(
toneId
:
number
)
=>
{
const
className
=
'w-[14px] h-[14px]'
const
res
=
({
1
:
<
Brush01
className
=
{
className
}
/>
,
2
:
<
Scales02
className
=
{
className
}
/>
,
3
:
<
Target04
className
=
{
className
}
/>
,
4
:
<
Sliders02
className
=
{
className
}
/>
,
})[
toneId
]
return
res
}
return
(
<
PortalToFollowElem
open=
{
open
}
...
...
@@ -241,6 +300,47 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
<
div
className=
'mt-5'
><
Loading
/></
div
>
)
}
{
[
'openai'
,
'azure_openai'
].
includes
(
provider
)
&&
!
isLoading
&&
!!
parameterRules
.
length
&&
(
<
div
className=
'mt-5 mb-4'
>
<
div
className=
"mb-3 text-sm text-gray-900"
>
{
t
(
'appDebug.modelConfig.setTone'
)
}
</
div
>
<
Radio
.
Group
className=
{
cn
(
'!rounded-lg'
,
toneTabBgClassName
)
}
value=
{
toneId
}
onChange=
{
handleToneChange
}
>
<>
{
TONE_LIST
.
slice
(
0
,
3
).
map
(
tone
=>
(
<
div
className=
'grow flex items-center'
key=
{
tone
.
id
}
>
<
Radio
value=
{
tone
.
id
}
className=
{
cn
(
tone
.
id
===
toneId
&&
'rounded-md border border-gray-200 shadow-md'
,
'!mr-0 grow !px-1 sm:!px-2 !justify-center text-[13px] font-medium'
)
}
labelClassName=
{
cn
(
tone
.
id
===
toneId
?
({
1
:
'text-[#6938EF]'
,
2
:
'text-[#444CE7]'
,
3
:
'text-[#107569]'
,
})[
toneId
]
:
'text-[#667085]'
,
'flex items-center space-x-2'
)
}
>
<>
{
getToneIcon
(
tone
.
id
)
}
{
!
isMobile
&&
<
div
>
{
t
(
`common.model.tone.${tone.name}`
)
as
string
}
</
div
>
}
<
div
className=
""
></
div
>
</>
</
Radio
>
{
tone
.
id
!==
toneId
&&
tone
.
id
+
1
!==
toneId
&&
(<
div
className=
'h-5 border-r border-gray-200'
></
div
>)
}
</
div
>
))
}
</>
<
Radio
value=
{
TONE_LIST
[
3
].
id
}
className=
{
cn
(
toneId
===
4
&&
'rounded-md border border-gray-200 shadow-md'
,
'!mr-0 grow !px-1 sm:!px-2 !justify-center text-[13px] font-medium'
)
}
labelClassName=
{
cn
(
'flex items-center space-x-2 '
,
toneId
===
4
?
'text-[#155EEF]'
:
'text-[#667085]'
)
}
>
<>
{
getToneIcon
(
TONE_LIST
[
3
].
id
)
}
{
!
isMobile
&&
<
div
>
{
t
(
`common.model.tone.${TONE_LIST[3].name}`
)
as
string
}
</
div
>
}
</>
</
Radio
>
</
Radio
.
Group
>
</
div
>
)
}
{
!
isLoading
&&
!!
parameterRules
.
length
&&
(
[
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment