config-param-modal.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import ScoreSlider from './score-slider'
  6. import { Item } from './config-param'
  7. import Modal from '@/app/components/base/modal'
  8. import Button from '@/app/components/base/button'
  9. import Toast from '@/app/components/base/toast'
  10. import type { AnnotationReplyConfig } from '@/models/debug'
  11. import { ANNOTATION_DEFAULT } from '@/config'
  12. import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
  13. import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
  14. import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
  15. type Props = {
  16. appId: string
  17. isShow: boolean
  18. onHide: () => void
  19. onSave: (embeddingModel: {
  20. embedding_provider_name: string
  21. embedding_model_name: string
  22. }, score: number) => void
  23. isInit?: boolean
  24. annotationConfig: AnnotationReplyConfig
  25. }
  26. const ConfigParamModal: FC<Props> = ({
  27. isShow,
  28. onHide: doHide,
  29. onSave,
  30. isInit,
  31. annotationConfig: oldAnnotationConfig,
  32. }) => {
  33. const { t } = useTranslation()
  34. const {
  35. modelList: embeddingsModelList,
  36. defaultModel: embeddingsDefaultModel,
  37. currentModel: isEmbeddingsDefaultModelValid,
  38. } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.textEmbedding)
  39. const [annotationConfig, setAnnotationConfig] = useState(oldAnnotationConfig)
  40. const [isLoading, setLoading] = useState(false)
  41. const [embeddingModel, setEmbeddingModel] = useState(oldAnnotationConfig.embedding_model
  42. ? {
  43. providerName: oldAnnotationConfig.embedding_model.embedding_provider_name,
  44. modelName: oldAnnotationConfig.embedding_model.embedding_model_name,
  45. }
  46. : (embeddingsDefaultModel
  47. ? {
  48. providerName: embeddingsDefaultModel.provider.provider,
  49. modelName: embeddingsDefaultModel.model,
  50. }
  51. : undefined))
  52. const onHide = () => {
  53. if (!isLoading)
  54. doHide()
  55. }
  56. const handleSave = async () => {
  57. if (!embeddingModel || !embeddingModel.modelName || (embeddingModel.modelName === embeddingsDefaultModel?.model && !isEmbeddingsDefaultModelValid)) {
  58. Toast.notify({
  59. message: t('common.modelProvider.embeddingModel.required'),
  60. type: 'error',
  61. })
  62. return
  63. }
  64. setLoading(true)
  65. await onSave({
  66. embedding_provider_name: embeddingModel.providerName,
  67. embedding_model_name: embeddingModel.modelName,
  68. }, annotationConfig.score_threshold)
  69. setLoading(false)
  70. }
  71. return (
  72. <Modal
  73. isShow={isShow}
  74. onClose={onHide}
  75. className='!p-8 !pb-6 !mt-14 !max-w-none !w-[640px]'
  76. >
  77. <div className='mb-2 text-xl font-semibold text-[#1D2939]'>
  78. {t(`appAnnotation.initSetup.${isInit ? 'title' : 'configTitle'}`)}
  79. </div>
  80. <div className='mt-6 space-y-3'>
  81. <Item
  82. title={t('appDebug.feature.annotation.scoreThreshold.title')}
  83. tooltip={t('appDebug.feature.annotation.scoreThreshold.description')}
  84. >
  85. <ScoreSlider
  86. className='mt-1'
  87. value={(annotationConfig.score_threshold || ANNOTATION_DEFAULT.score_threshold) * 100}
  88. onChange={(val) => {
  89. setAnnotationConfig({
  90. ...annotationConfig,
  91. score_threshold: val / 100,
  92. })
  93. }}
  94. />
  95. </Item>
  96. <Item
  97. title={t('common.modelProvider.embeddingModel.key')}
  98. tooltip={t('appAnnotation.embeddingModelSwitchTip')}
  99. >
  100. <div className='pt-1'>
  101. <ModelSelector
  102. defaultModel={embeddingModel && {
  103. provider: embeddingModel.providerName,
  104. model: embeddingModel.modelName,
  105. }}
  106. modelList={embeddingsModelList}
  107. onSelect={(val) => {
  108. setEmbeddingModel({
  109. providerName: val.provider,
  110. modelName: val.model,
  111. })
  112. }}
  113. />
  114. </div>
  115. </Item>
  116. </div>
  117. <div className='mt-6 flex gap-2 justify-end'>
  118. <Button onClick={onHide}>{t('common.operation.cancel')}</Button>
  119. <Button
  120. variant='primary'
  121. onClick={handleSave}
  122. loading={isLoading}
  123. >
  124. <div></div>
  125. <div>{t(`appAnnotation.initSetup.${isInit ? 'confirmBtn' : 'configConfirmBtn'}`)}</div>
  126. </Button >
  127. </div >
  128. </Modal >
  129. )
  130. }
  131. export default React.memo(ConfigParamModal)