123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- import React, { useState } from 'react'
- import { useTranslation } from 'react-i18next'
- import {
- RiEqualizer2Line,
- } from '@remixicon/react'
- import Button from '../../base/button'
- import Tag from '../../base/tag'
- import { getIcon } from '../common/retrieval-method-info'
- import s from './style.module.css'
- import ModifyExternalRetrievalModal from './modify-external-retrieval-modal'
- import Tooltip from '@/app/components/base/tooltip'
- import cn from '@/utils/classnames'
- import type { ExternalKnowledgeBaseHitTestingResponse, HitTestingResponse } from '@/models/datasets'
- import { externalKnowledgeBaseHitTesting, hitTesting } from '@/service/datasets'
- import { asyncRunSafe } from '@/utils'
- import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
- type TextAreaWithButtonIProps = {
- datasetId: string
- onUpdateList: () => void
- setHitResult: (res: HitTestingResponse) => void
- setExternalHitResult: (res: ExternalKnowledgeBaseHitTestingResponse) => void
- loading: boolean
- setLoading: (v: boolean) => void
- text: string
- setText: (v: string) => void
- isExternal?: boolean
- onClickRetrievalMethod: () => void
- retrievalConfig: RetrievalConfig
- isEconomy: boolean
- onSubmit?: () => void
- }
- const TextAreaWithButton = ({
- datasetId,
- onUpdateList,
- setHitResult,
- setExternalHitResult,
- setLoading,
- loading,
- text,
- setText,
- isExternal = false,
- onClickRetrievalMethod,
- retrievalConfig,
- isEconomy,
- onSubmit: _onSubmit,
- }: TextAreaWithButtonIProps) => {
- const { t } = useTranslation()
- const [isSettingsOpen, setIsSettingsOpen] = useState(false)
- const [externalRetrievalSettings, setExternalRetrievalSettings] = useState({
- top_k: 2,
- score_threshold: 0.5,
- score_threshold_enabled: false,
- })
- const handleSaveExternalRetrievalSettings = (data: { top_k: number; score_threshold: number; score_threshold_enabled: boolean }) => {
- setExternalRetrievalSettings(data)
- setIsSettingsOpen(false)
- }
- function handleTextChange(event: any) {
- setText(event.target.value)
- }
- const onSubmit = async () => {
- setLoading(true)
- const [e, res] = await asyncRunSafe<HitTestingResponse>(
- hitTesting({
- datasetId,
- queryText: text,
- retrieval_model: {
- ...retrievalConfig,
- search_method: isEconomy ? RETRIEVE_METHOD.keywordSearch : retrievalConfig.search_method,
- },
- }) as Promise<HitTestingResponse>,
- )
- if (!e) {
- setHitResult(res)
- onUpdateList?.()
- }
- setLoading(false)
- _onSubmit && _onSubmit()
- }
- const externalRetrievalTestingOnSubmit = async () => {
- const [e, res] = await asyncRunSafe<ExternalKnowledgeBaseHitTestingResponse>(
- externalKnowledgeBaseHitTesting({
- datasetId,
- query: text,
- external_retrieval_model: {
- top_k: externalRetrievalSettings.top_k,
- score_threshold: externalRetrievalSettings.score_threshold,
- score_threshold_enabled: externalRetrievalSettings.score_threshold_enabled,
- },
- }) as Promise<ExternalKnowledgeBaseHitTestingResponse>,
- )
- if (!e) {
- setExternalHitResult(res)
- onUpdateList?.()
- }
- setLoading(false)
- }
- const retrievalMethod = isEconomy ? RETRIEVE_METHOD.invertedIndex : retrievalConfig.search_method
- const Icon = getIcon(retrievalMethod)
- return (
- <>
- <div className={s.wrapper}>
- <div className='relative pt-2 rounded-tl-xl rounded-tr-xl bg-[#EEF4FF]'>
- <div className="px-4 pb-2 flex justify-between h-8 items-center">
- <span className="text-gray-800 font-semibold text-sm">
- {t('datasetHitTesting.input.title')}
- </span>
- {isExternal
- ? <Button
- variant='secondary'
- size='small'
- onClick={() => setIsSettingsOpen(!isSettingsOpen)}
- >
- <RiEqualizer2Line className='text-components-button-secondary-text w-3.5 h-3.5' />
- <div className='flex px-[3px] justify-center items-center gap-1'>
- <span className='text-components-button-secondary-text system-xs-medium'>{t('datasetHitTesting.settingTitle')}</span>
- </div>
- </Button>
- : <Tooltip
- popupContent={t('dataset.retrieval.changeRetrievalMethod')}
- >
- <div
- onClick={onClickRetrievalMethod}
- className='flex px-2 h-7 items-center space-x-1 bg-white hover:bg-[#ECE9FE] rounded-md shadow-sm cursor-pointer text-[#6927DA]'
- >
- <Icon className='w-3.5 h-3.5'></Icon>
- <div className='text-xs font-medium'>{t(`dataset.retrieval.${retrievalMethod}.title`)}</div>
- </div>
- </Tooltip>
- }
- </div>
- {
- isSettingsOpen && (
- <ModifyExternalRetrievalModal
- onClose={() => setIsSettingsOpen(false)}
- onSave={handleSaveExternalRetrievalSettings}
- initialTopK={externalRetrievalSettings.top_k}
- initialScoreThreshold={externalRetrievalSettings.score_threshold}
- initialScoreThresholdEnabled={externalRetrievalSettings.score_threshold_enabled}
- />
- )
- }
- <div className='h-2 rounded-tl-xl rounded-tr-xl bg-white'></div>
- </div>
- <div className='px-4 pb-11'>
- <textarea
- className='h-[220px] border-none resize-none font-normal caret-primary-600 text-gray-700 text-sm w-full focus-visible:outline-none placeholder:text-gray-300 placeholder:text-sm placeholder:font-normal'
- value={text}
- onChange={handleTextChange}
- placeholder={t('datasetHitTesting.input.placeholder') as string}
- />
- <div className="absolute inset-x-0 bottom-0 flex items-center justify-between mx-4 mt-2 mb-2">
- {text?.length > 200
- ? (
- <Tooltip
- popupContent={t('datasetHitTesting.input.countWarning')}
- >
- <div>
- <Tag color="red" className="!text-red-600">
- {text?.length}
- <span className="text-red-300 mx-0.5">/</span>
- 200
- </Tag>
- </div>
- </Tooltip>
- )
- : (
- <Tag
- color="gray"
- className={cn('!text-gray-500', text?.length ? '' : 'opacity-50')}
- >
- {text?.length}
- <span className="text-gray-300 mx-0.5">/</span>
- 200
- </Tag>
- )}
- <div>
- <Button
- onClick={isExternal ? externalRetrievalTestingOnSubmit : onSubmit}
- variant="primary"
- loading={loading}
- disabled={(!text?.length || text?.length > 200)}
- >
- {t('datasetHitTesting.input.testing')}
- </Button>
- </div>
- </div>
- </div>
- </div>
- </>
- )
- }
- export default TextAreaWithButton
|