mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 09:58:04 +08:00
chore(web): new lint setup (#30020)
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { HitTestingChildChunk } from '@/models/datasets'
|
||||
import React from 'react'
|
||||
import { SliceContent } from '../../formatted-text/flavours/shared'
|
||||
import Score from './score'
|
||||
import type { HitTestingChildChunk } from '@/models/datasets'
|
||||
|
||||
type Props = {
|
||||
payload: HitTestingChildChunk
|
||||
@ -19,11 +19,14 @@ const ChildChunks: FC<Props> = ({
|
||||
<div
|
||||
className={!isShowAll ? 'line-clamp-2 break-all' : ''}
|
||||
>
|
||||
<div className='relative top-[-2px] inline-flex items-center'>
|
||||
<div className='system-2xs-semibold-uppercase flex h-[20.5px] items-center bg-state-accent-solid px-1 text-text-primary-on-surface'>C-{position}</div>
|
||||
<div className="relative top-[-2px] inline-flex items-center">
|
||||
<div className="system-2xs-semibold-uppercase flex h-[20.5px] items-center bg-state-accent-solid px-1 text-text-primary-on-surface">
|
||||
C-
|
||||
{position}
|
||||
</div>
|
||||
<Score value={score} besideChunkName />
|
||||
</div>
|
||||
<SliceContent className='bg-state-accent-hover py-0.5 text-sm font-normal text-text-secondary group-hover:bg-state-accent-hover'>{content}</SliceContent>
|
||||
<SliceContent className="bg-state-accent-hover py-0.5 text-sm font-normal text-text-secondary group-hover:bg-state-accent-hover">{content}</SliceContent>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
'use client'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import type { HitTesting } from '@/models/datasets'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
|
||||
import Dot from '../../documents/detail/completed/common/dot'
|
||||
import Score from './score'
|
||||
import ChildChunksItem from './child-chunks-item'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import type { HitTesting } from '@/models/datasets'
|
||||
import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import ImageList from '../../common/image-list'
|
||||
import Dot from '../../documents/detail/completed/common/dot'
|
||||
import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
|
||||
import ChildChunksItem from './child-chunks-item'
|
||||
import Mask from './mask'
|
||||
import Score from './score'
|
||||
|
||||
const i18nPrefix = 'datasetHitTesting'
|
||||
|
||||
@ -35,7 +35,8 @@ const ChunkDetailModal = ({
|
||||
const labelPrefix = isParentChildRetrieval ? t('datasetDocuments.segment.parentChunk') : t('datasetDocuments.segment.chunk')
|
||||
|
||||
const images = useMemo(() => {
|
||||
if (!files) return []
|
||||
if (!files)
|
||||
return []
|
||||
return files.map(file => ({
|
||||
name: file.name,
|
||||
mimeType: file.mime_type,
|
||||
@ -56,26 +57,26 @@ const ChunkDetailModal = ({
|
||||
onClose={onHide}
|
||||
className={cn(isParentChildRetrieval ? '!min-w-[1200px]' : '!min-w-[800px]')}
|
||||
>
|
||||
<div className='mt-4 flex'>
|
||||
<div className="mt-4 flex">
|
||||
<div className={cn('flex-1', isParentChildRetrieval && 'pr-6')}>
|
||||
{/* Meta info */}
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex grow items-center space-x-2'>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex grow items-center space-x-2">
|
||||
<SegmentIndexTag
|
||||
labelPrefix={labelPrefix}
|
||||
positionId={position}
|
||||
className={cn('w-fit group-hover:opacity-100')}
|
||||
/>
|
||||
<Dot />
|
||||
<div className='flex grow items-center space-x-1'>
|
||||
<FileIcon type={extension} size='sm' />
|
||||
<span className='w-0 grow truncate text-[13px] font-normal text-text-secondary'>{document.name}</span>
|
||||
<div className="flex grow items-center space-x-1">
|
||||
<FileIcon type={extension} size="sm" />
|
||||
<span className="w-0 grow truncate text-[13px] font-normal text-text-secondary">{document.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Score value={score} />
|
||||
</div>
|
||||
{/* Content */}
|
||||
<div className='relative'>
|
||||
<div className="relative">
|
||||
{!answer && (
|
||||
<Markdown
|
||||
className={cn('!mt-2 !text-text-secondary', heighClassName)}
|
||||
@ -84,15 +85,15 @@ const ChunkDetailModal = ({
|
||||
/>
|
||||
)}
|
||||
{answer && (
|
||||
<div className='break-all'>
|
||||
<div className='flex gap-x-1'>
|
||||
<div className='w-4 shrink-0 text-[13px] font-medium leading-[20px] text-text-tertiary'>Q</div>
|
||||
<div className="break-all">
|
||||
<div className="flex gap-x-1">
|
||||
<div className="w-4 shrink-0 text-[13px] font-medium leading-[20px] text-text-tertiary">Q</div>
|
||||
<div className={cn('body-md-regular line-clamp-20 text-text-secondary')}>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-x-1'>
|
||||
<div className='w-4 shrink-0 text-[13px] font-medium leading-[20px] text-text-tertiary'>A</div>
|
||||
<div className="flex gap-x-1">
|
||||
<div className="w-4 shrink-0 text-[13px] font-medium leading-[20px] text-text-tertiary">A</div>
|
||||
<div className={cn('body-md-regular line-clamp-20 text-text-secondary')}>
|
||||
{answer}
|
||||
</div>
|
||||
@ -100,17 +101,17 @@ const ChunkDetailModal = ({
|
||||
</div>
|
||||
)}
|
||||
{/* Mask */}
|
||||
<Mask className='absolute inset-x-0 bottom-0' />
|
||||
<Mask className="absolute inset-x-0 bottom-0" />
|
||||
</div>
|
||||
{(showImages || showKeywords) && (
|
||||
<div className='flex flex-col gap-y-3 pt-3'>
|
||||
<div className="flex flex-col gap-y-3 pt-3">
|
||||
{showImages && (
|
||||
<ImageList images={images} size='md' className='py-1' />
|
||||
<ImageList images={images} size="md" className="py-1" />
|
||||
)}
|
||||
{showKeywords && (
|
||||
<div className='flex flex-col gap-y-1'>
|
||||
<div className='text-xs font-medium uppercase text-text-tertiary'>{t(`${i18nPrefix}.keyword`)}</div>
|
||||
<div className='flex flex-wrap gap-x-2'>
|
||||
<div className="flex flex-col gap-y-1">
|
||||
<div className="text-xs font-medium uppercase text-text-tertiary">{t(`${i18nPrefix}.keyword`)}</div>
|
||||
<div className="flex flex-wrap gap-x-2">
|
||||
{keywords.map(keyword => (
|
||||
<Tag key={keyword} text={keyword} />
|
||||
))}
|
||||
@ -122,8 +123,8 @@ const ChunkDetailModal = ({
|
||||
</div>
|
||||
|
||||
{isParentChildRetrieval && (
|
||||
<div className='flex-1 pb-6 pl-6'>
|
||||
<div className='system-xs-semibold-uppercase text-text-secondary'>{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
|
||||
<div className="flex-1 pb-6 pl-6">
|
||||
<div className="system-xs-semibold-uppercase text-text-secondary">{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
|
||||
<div className={cn('mt-1 space-y-2', heighClassName)}>
|
||||
{child_chunks.map(item => (
|
||||
<ChildChunksItem key={item.id} payload={item} isShowAll />
|
||||
|
||||
@ -4,12 +4,14 @@ import { useTranslation } from 'react-i18next'
|
||||
|
||||
const EmptyRecords = () => {
|
||||
const { t } = useTranslation()
|
||||
return <div className='rounded-2xl bg-workflow-process-bg p-5'>
|
||||
<div className='flex h-10 w-10 items-center justify-center rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'>
|
||||
<RiHistoryLine className='h-5 w-5 text-text-tertiary' />
|
||||
return (
|
||||
<div className="rounded-2xl bg-workflow-process-bg p-5">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg p-1 shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]">
|
||||
<RiHistoryLine className="h-5 w-5 text-text-tertiary" />
|
||||
</div>
|
||||
<div className="my-2 text-[13px] font-medium leading-4 text-text-tertiary">{t('datasetHitTesting.noRecentTip')}</div>
|
||||
</div>
|
||||
<div className='my-2 text-[13px] font-medium leading-4 text-text-tertiary'>{t('datasetHitTesting.noRecentTip')}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(EmptyRecords)
|
||||
|
||||
@ -12,7 +12,8 @@ export const Mask = ({
|
||||
<div className={cn(
|
||||
'h-12 bg-gradient-to-b from-components-panel-bg-transparent to-components-panel-bg',
|
||||
className,
|
||||
)} />
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
import type { UseMutateAsyncFunction } from '@tanstack/react-query'
|
||||
import type { ChangeEvent } from 'react'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiEqualizer2Line,
|
||||
RiPlayCircleLine,
|
||||
} from '@remixicon/react'
|
||||
import Image from 'next/image'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { getIcon } from '@/app/components/datasets/common/retrieval-method-info'
|
||||
import ModifyExternalRetrievalModal from '@/app/components/datasets/hit-testing/modify-external-retrieval-modal'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import type { FileEntity } from '@/app/components/datasets/common/image-uploader/types'
|
||||
import type {
|
||||
Attachment,
|
||||
ExternalKnowledgeBaseHitTestingRequest,
|
||||
@ -18,13 +9,23 @@ import type {
|
||||
HitTestingResponse,
|
||||
Query,
|
||||
} from '@/models/datasets'
|
||||
import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app'
|
||||
import type { UseMutateAsyncFunction } from '@tanstack/react-query'
|
||||
import ImageUploaderInRetrievalTesting from '@/app/components/datasets/common/image-uploader/image-uploader-in-retrieval-testing'
|
||||
import Textarea from './textarea'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
import type { FileEntity } from '@/app/components/datasets/common/image-uploader/types'
|
||||
import type { RetrievalConfig } from '@/types/app'
|
||||
import {
|
||||
RiEqualizer2Line,
|
||||
RiPlayCircleLine,
|
||||
} from '@remixicon/react'
|
||||
import Image from 'next/image'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import Button from '@/app/components/base/button'
|
||||
import ImageUploaderInRetrievalTesting from '@/app/components/datasets/common/image-uploader/image-uploader-in-retrieval-testing'
|
||||
import { getIcon } from '@/app/components/datasets/common/retrieval-method-info'
|
||||
import ModifyExternalRetrievalModal from '@/app/components/datasets/hit-testing/modify-external-retrieval-modal'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
import { RETRIEVE_METHOD } from '@/types/app'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Textarea from './textarea'
|
||||
|
||||
type QueryInputProps = {
|
||||
onUpdateList: () => void
|
||||
@ -176,7 +177,7 @@ const QueryInput = ({
|
||||
}, [text, externalRetrievalSettings, externalKnowledgeBaseHitTestingMutation, onUpdateList, setExternalHitResult])
|
||||
|
||||
const retrievalMethod = isEconomy ? RETRIEVE_METHOD.keywordSearch : retrievalConfig.search_method
|
||||
const icon = <Image className='size-3.5 text-util-colors-purple-purple-600' src={getIcon(retrievalMethod)} alt='' />
|
||||
const icon = <Image className="size-3.5 text-util-colors-purple-purple-600" src={getIcon(retrievalMethod)} alt="" />
|
||||
const TextAreaComp = useMemo(() => {
|
||||
return (
|
||||
<Textarea
|
||||
@ -189,12 +190,12 @@ const QueryInput = ({
|
||||
return (
|
||||
<Button
|
||||
onClick={isExternal ? externalRetrievalTestingOnSubmit : onSubmit}
|
||||
variant='primary'
|
||||
variant="primary"
|
||||
loading={loading}
|
||||
disabled={(text.length === 0 && images.length === 0) || text.length > 200 || (images.length > 0 && !isAllUploaded)}
|
||||
className='w-[88px]'
|
||||
className="w-[88px]"
|
||||
>
|
||||
<RiPlayCircleLine className='mr-1 size-4' />
|
||||
<RiPlayCircleLine className="mr-1 size-4" />
|
||||
{t('datasetHitTesting.input.testing')}
|
||||
</Button>
|
||||
)
|
||||
@ -202,32 +203,34 @@ const QueryInput = ({
|
||||
|
||||
return (
|
||||
<div className={cn('relative flex h-80 shrink-0 flex-col overflow-hidden rounded-xl bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2 p-0.5 shadow-xs')}>
|
||||
<div className='flex h-full flex-col overflow-hidden rounded-[10px] bg-background-section-burn'>
|
||||
<div className='relative flex shrink-0 items-center justify-between p-1.5 pb-1 pl-3'>
|
||||
<span className='system-sm-semibold-uppercase text-text-secondary'>
|
||||
<div className="flex h-full flex-col overflow-hidden rounded-[10px] bg-background-section-burn">
|
||||
<div className="relative flex shrink-0 items-center justify-between p-1.5 pb-1 pl-3">
|
||||
<span className="system-sm-semibold-uppercase text-text-secondary">
|
||||
{t('datasetHitTesting.input.title')}
|
||||
</span>
|
||||
{isExternal ? (
|
||||
<Button
|
||||
variant='secondary'
|
||||
size='small'
|
||||
onClick={() => setIsSettingsOpen(!isSettingsOpen)}
|
||||
>
|
||||
<RiEqualizer2Line className='h-3.5 w-3.5 text-components-button-secondary-text' />
|
||||
<div className='flex items-center justify-center gap-1 px-[3px]'>
|
||||
<span className='system-xs-medium text-components-button-secondary-text'>{t('datasetHitTesting.settingTitle')}</span>
|
||||
</div>
|
||||
</Button>
|
||||
) : (
|
||||
<div
|
||||
onClick={onClickRetrievalMethod}
|
||||
className='flex h-7 cursor-pointer items-center space-x-0.5 rounded-lg border-[0.5px] border-components-button-secondary-bg bg-components-button-secondary-bg px-1.5 shadow-xs backdrop-blur-[5px] hover:bg-components-button-secondary-bg-hover'
|
||||
>
|
||||
{icon}
|
||||
<div className='text-xs font-medium uppercase text-text-secondary'>{t(`dataset.retrieval.${retrievalMethod}.title`)}</div>
|
||||
<RiEqualizer2Line className='size-4 text-components-menu-item-text'></RiEqualizer2Line>
|
||||
</div>
|
||||
)}
|
||||
{isExternal
|
||||
? (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={() => setIsSettingsOpen(!isSettingsOpen)}
|
||||
>
|
||||
<RiEqualizer2Line className="h-3.5 w-3.5 text-components-button-secondary-text" />
|
||||
<div className="flex items-center justify-center gap-1 px-[3px]">
|
||||
<span className="system-xs-medium text-components-button-secondary-text">{t('datasetHitTesting.settingTitle')}</span>
|
||||
</div>
|
||||
</Button>
|
||||
)
|
||||
: (
|
||||
<div
|
||||
onClick={onClickRetrievalMethod}
|
||||
className="flex h-7 cursor-pointer items-center space-x-0.5 rounded-lg border-[0.5px] border-components-button-secondary-bg bg-components-button-secondary-bg px-1.5 shadow-xs backdrop-blur-[5px] hover:bg-components-button-secondary-bg-hover"
|
||||
>
|
||||
{icon}
|
||||
<div className="text-xs font-medium uppercase text-text-secondary">{t(`dataset.retrieval.${retrievalMethod}.title`)}</div>
|
||||
<RiEqualizer2Line className="size-4 text-components-menu-item-text"></RiEqualizer2Line>
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
isSettingsOpen && (
|
||||
<ModifyExternalRetrievalModal
|
||||
@ -246,8 +249,8 @@ const QueryInput = ({
|
||||
onChange={handleImageChange}
|
||||
value={images}
|
||||
showUploader={isMultimodal}
|
||||
className='grow'
|
||||
actionAreaClassName='px-4 py-2 shrink-0 bg-background-default'
|
||||
className="grow"
|
||||
actionAreaClassName="px-4 py-2 shrink-0 bg-background-default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import type { ChangeEvent } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { Corner } from '@/app/components/base/icons/src/vender/solid/shapes'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { cn } from '@/utils/classnames'
|
||||
|
||||
type TextareaProps = {
|
||||
text: string
|
||||
@ -20,39 +20,41 @@ const Textarea = ({
|
||||
<div className={cn(
|
||||
'relative flex-1 overflow-hidden rounded-t-[10px] border-t-[0.5px] border-components-panel-border-subtle bg-background-default px-4 pb-0 pt-3',
|
||||
text.length > 200 && 'border-state-destructive-active',
|
||||
)}>
|
||||
)}
|
||||
>
|
||||
<textarea
|
||||
className='system-md-regular h-full w-full resize-none border-none bg-transparent text-text-secondary caret-[#295EFF] placeholder:text-components-input-text-placeholder focus-visible:outline-none'
|
||||
className="system-md-regular h-full w-full resize-none border-none bg-transparent text-text-secondary caret-[#295EFF] placeholder:text-components-input-text-placeholder focus-visible:outline-none"
|
||||
value={text}
|
||||
onChange={handleTextChange}
|
||||
placeholder={t('datasetHitTesting.input.placeholder') as string}
|
||||
/>
|
||||
<div className='absolute right-0 top-0 flex items-center'>
|
||||
<div className="absolute right-0 top-0 flex items-center">
|
||||
<Corner className={cn(
|
||||
'text-background-section-burn',
|
||||
text.length > 200 && 'text-util-colors-red-red-100',
|
||||
)} />
|
||||
)}
|
||||
/>
|
||||
{text.length > 200
|
||||
? (
|
||||
<Tooltip
|
||||
popupContent={t('datasetHitTesting.input.countWarning')}
|
||||
>
|
||||
<Tooltip
|
||||
popupContent={t('datasetHitTesting.input.countWarning')}
|
||||
>
|
||||
<div
|
||||
className={cn('system-2xs-medium-uppercase bg-util-colors-red-red-100 py-1 pr-2 text-util-colors-red-red-600')}
|
||||
>
|
||||
{`${text.length}/200`}
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
: (
|
||||
<div
|
||||
className={cn('system-2xs-medium-uppercase bg-util-colors-red-red-100 py-1 pr-2 text-util-colors-red-red-600')}
|
||||
className={cn(
|
||||
'system-2xs-medium-uppercase bg-background-section-burn py-1 pr-2 text-text-tertiary',
|
||||
)}
|
||||
>
|
||||
{`${text.length}/200`}
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
: (
|
||||
<div
|
||||
className={cn(
|
||||
'system-2xs-medium-uppercase bg-background-section-burn py-1 pr-2 text-text-tertiary',
|
||||
)}
|
||||
>
|
||||
{`${text.length}/200`}
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import type { Attachment, HitTestingRecord, Query } from '@/models/datasets'
|
||||
import { RiApps2Line, RiArrowDownLine, RiFocus2Line } from '@remixicon/react'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ImageList from '../../common/image-list'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import ImageList from '../../common/image-list'
|
||||
|
||||
type RecordsProps = {
|
||||
records: HitTestingRecord[]
|
||||
@ -45,15 +45,15 @@ const Records = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='grow overflow-y-auto'>
|
||||
<table className={'w-full border-collapse border-0 text-[13px] leading-4 text-text-secondary '}>
|
||||
<thead className='sticky top-0 h-7 text-xs font-medium uppercase leading-7 text-text-tertiary backdrop-blur-[5px]'>
|
||||
<div className="grow overflow-y-auto">
|
||||
<table className="w-full border-collapse border-0 text-[13px] leading-4 text-text-secondary ">
|
||||
<thead className="sticky top-0 h-7 text-xs font-medium uppercase leading-7 text-text-tertiary backdrop-blur-[5px]">
|
||||
<tr>
|
||||
<td className='rounded-l-lg bg-background-section-burn pl-3'>{t('datasetHitTesting.table.header.queryContent')}</td>
|
||||
<td className='w-[128px] bg-background-section-burn pl-3'>{t('datasetHitTesting.table.header.source')}</td>
|
||||
<td className='w-48 rounded-r-lg bg-background-section-burn pl-3'>
|
||||
<td className="rounded-l-lg bg-background-section-burn pl-3">{t('datasetHitTesting.table.header.queryContent')}</td>
|
||||
<td className="w-[128px] bg-background-section-burn pl-3">{t('datasetHitTesting.table.header.source')}</td>
|
||||
<td className="w-48 rounded-r-lg bg-background-section-burn pl-3">
|
||||
<div
|
||||
className='flex cursor-pointer items-center'
|
||||
className="flex cursor-pointer items-center"
|
||||
onClick={handleSortTime}
|
||||
>
|
||||
{t('datasetHitTesting.table.header.time')}
|
||||
@ -76,33 +76,33 @@ const Records = ({
|
||||
return (
|
||||
<tr
|
||||
key={id}
|
||||
className='group cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover'
|
||||
className="group cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover"
|
||||
onClick={() => onClickRecord(record)}
|
||||
>
|
||||
<td className='max-w-xs p-3 pr-2'>
|
||||
<div className='flex flex-col gap-y-1'>
|
||||
<td className="max-w-xs p-3 pr-2">
|
||||
<div className="flex flex-col gap-y-1">
|
||||
{content && (
|
||||
<div className='line-clamp-2'>
|
||||
<div className="line-clamp-2">
|
||||
{content}
|
||||
</div>
|
||||
)}
|
||||
{images.length > 0 && (
|
||||
<ImageList
|
||||
images={images}
|
||||
size='md'
|
||||
className='py-1'
|
||||
size="md"
|
||||
className="py-1"
|
||||
limit={5}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className='w-[128px] p-3 pr-2'>
|
||||
<div className='flex items-center'>
|
||||
<SourceIcon className='mr-1 size-4 text-text-tertiary' />
|
||||
<span className='capitalize'>{source.replace('_', ' ').replace('hit testing', 'retrieval test')}</span>
|
||||
<td className="w-[128px] p-3 pr-2">
|
||||
<div className="flex items-center">
|
||||
<SourceIcon className="mr-1 size-4 text-text-tertiary" />
|
||||
<span className="capitalize">{source.replace('_', ' ').replace('hit testing', 'retrieval test')}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className='w-48 p-3 pr-2'>
|
||||
<td className="w-48 p-3 pr-2">
|
||||
{formatTime(created_at, t('datasetHitTesting.dateTimeFormat') as string)}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { ExternalKnowledgeBaseHitTesting } from '@/models/datasets'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import ResultItemMeta from './result-item-meta'
|
||||
import ResultItemFooter from './result-item-footer'
|
||||
import type { ExternalKnowledgeBaseHitTesting } from '@/models/datasets'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import ResultItemFooter from './result-item-footer'
|
||||
import ResultItemMeta from './result-item-meta'
|
||||
|
||||
const i18nPrefix = 'datasetHitTesting'
|
||||
type Props = {
|
||||
@ -27,11 +27,11 @@ const ResultItemExternal: FC<Props> = ({ payload, positionId }) => {
|
||||
return (
|
||||
<div className={cn('cursor-pointer rounded-xl bg-chat-bubble-bg pt-3 hover:shadow-lg')} onClick={showDetailModal}>
|
||||
{/* Meta info */}
|
||||
<ResultItemMeta className='px-3' labelPrefix={'Chunk'} positionId={positionId} wordCount={content.length} score={score} />
|
||||
<ResultItemMeta className="px-3" labelPrefix="Chunk" positionId={positionId} wordCount={content.length} score={score} />
|
||||
|
||||
{/* Main */}
|
||||
<div className='mt-1 px-3'>
|
||||
<div className='body-md-regular line-clamp-2 break-all text-text-primary'>{content}</div>
|
||||
<div className="mt-1 px-3">
|
||||
<div className="body-md-regular line-clamp-2 break-all text-text-primary">{content}</div>
|
||||
</div>
|
||||
|
||||
{/* Foot */}
|
||||
@ -40,13 +40,13 @@ const ResultItemExternal: FC<Props> = ({ payload, positionId }) => {
|
||||
{isShowDetailModal && (
|
||||
<Modal
|
||||
title={t(`${i18nPrefix}.chunkDetail`)}
|
||||
className={'!min-w-[800px]'}
|
||||
className="!min-w-[800px]"
|
||||
closable
|
||||
onClose={hideDetailModal}
|
||||
isShow={isShowDetailModal}
|
||||
>
|
||||
<div className='mt-4 flex-1'>
|
||||
<ResultItemMeta labelPrefix={'Chunk'} positionId={positionId} wordCount={content.length} score={score} />
|
||||
<div className="mt-4 flex-1">
|
||||
<ResultItemMeta labelPrefix="Chunk" positionId={positionId} wordCount={content.length} score={score} />
|
||||
<div className={cn('body-md-regular mt-2 break-all text-text-secondary', 'h-[min(539px,_80vh)] overflow-y-auto')}>
|
||||
{content}
|
||||
</div>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import { RiArrowRightUpLine } from '@remixicon/react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiArrowRightUpLine } from '@remixicon/react'
|
||||
import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
|
||||
type Props = {
|
||||
docType: FileAppearanceTypeEnum
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
|
||||
import Dot from '../../documents/detail/completed/common/dot'
|
||||
import Score from './score'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Dot from '../../documents/detail/completed/common/dot'
|
||||
import { SegmentIndexTag } from '../../documents/detail/completed/common/segment-index-tag'
|
||||
import Score from './score'
|
||||
|
||||
type Props = {
|
||||
labelPrefix: string
|
||||
@ -34,7 +34,9 @@ const ResultItemMeta: FC<Props> = ({
|
||||
/>
|
||||
<Dot />
|
||||
<div className="system-xs-medium text-text-tertiary">
|
||||
{wordCount} {t('datasetDocuments.segment.characters', { count: wordCount })}
|
||||
{wordCount}
|
||||
{' '}
|
||||
{t('datasetDocuments.segment.characters', { count: wordCount })}
|
||||
</div>
|
||||
</div>
|
||||
<Score value={score} />
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
'use client'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import type { HitTesting } from '@/models/datasets'
|
||||
import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import ChildChunkItem from './child-chunks-item'
|
||||
import ChunkDetailModal from './chunk-detail-modal'
|
||||
import ResultItemMeta from './result-item-meta'
|
||||
import ResultItemFooter from './result-item-footer'
|
||||
import type { HitTesting } from '@/models/datasets'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
|
||||
import { extensionToFileType } from '@/app/components/datasets/hit-testing/utils/extension-to-file-type'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import ImageList from '../../common/image-list'
|
||||
import ChildChunkItem from './child-chunks-item'
|
||||
import ChunkDetailModal from './chunk-detail-modal'
|
||||
import ResultItemFooter from './result-item-footer'
|
||||
import ResultItemMeta from './result-item-meta'
|
||||
|
||||
const i18nPrefix = 'datasetHitTesting'
|
||||
type ResultItemProps = {
|
||||
@ -41,7 +41,8 @@ const ResultItem = ({
|
||||
}] = useBoolean(false)
|
||||
|
||||
const images = useMemo(() => {
|
||||
if (!files) return []
|
||||
if (!files)
|
||||
return []
|
||||
return files.map(file => ({
|
||||
name: file.name,
|
||||
mimeType: file.mime_type,
|
||||
@ -54,20 +55,20 @@ const ResultItem = ({
|
||||
return (
|
||||
<div className={cn('cursor-pointer rounded-xl bg-chat-bubble-bg pt-3 hover:shadow-lg')} onClick={showDetailModal}>
|
||||
{/* Meta info */}
|
||||
<ResultItemMeta className='px-3' labelPrefix={`${isParentChildRetrieval ? 'Parent-' : ''}Chunk`} positionId={position} wordCount={word_count} score={score} />
|
||||
<ResultItemMeta className="px-3" labelPrefix={`${isParentChildRetrieval ? 'Parent-' : ''}Chunk`} positionId={position} wordCount={word_count} score={score} />
|
||||
|
||||
{/* Main */}
|
||||
<div className='mt-1 px-3'>
|
||||
{<Markdown
|
||||
className='line-clamp-2'
|
||||
<div className="mt-1 px-3">
|
||||
<Markdown
|
||||
className="line-clamp-2"
|
||||
content={sign_content || content}
|
||||
customDisallowedElements={['input']}
|
||||
/>}
|
||||
/>
|
||||
{images.length > 0 && (
|
||||
<ImageList images={images} size='md' className='py-1' />
|
||||
<ImageList images={images} size="md" className="py-1" />
|
||||
)}
|
||||
{isParentChildRetrieval && (
|
||||
<div className='mt-1'>
|
||||
<div className="mt-1">
|
||||
<div
|
||||
className={cn('inline-flex h-6 cursor-pointer select-none items-center space-x-0.5 rounded-lg text-text-secondary', isFold && 'bg-workflow-process-bg pl-1')}
|
||||
onClick={(e) => {
|
||||
@ -76,12 +77,12 @@ const ResultItem = ({
|
||||
}}
|
||||
>
|
||||
<Icon className={cn('h-4 w-4', isFold && 'opacity-50')} />
|
||||
<div className='text-xs font-semibold uppercase'>{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
|
||||
<div className="text-xs font-semibold uppercase">{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
|
||||
</div>
|
||||
{!isFold && (
|
||||
<div className='space-y-2'>
|
||||
<div className="space-y-2">
|
||||
{child_chunks.map(item => (
|
||||
<div key={item.id} className='ml-[7px] border-l-[2px] border-text-accent-secondary pl-[7px]'>
|
||||
<div key={item.id} className="ml-[7px] border-l-[2px] border-text-accent-secondary pl-[7px]">
|
||||
<ChildChunkItem payload={item} isShowAll={false} />
|
||||
</div>
|
||||
))}
|
||||
@ -90,9 +91,9 @@ const ResultItem = ({
|
||||
</div>
|
||||
)}
|
||||
{!isParentChildRetrieval && keywords && keywords.length > 0 && (
|
||||
<div className='mt-2 flex flex-wrap'>
|
||||
<div className="mt-2 flex flex-wrap">
|
||||
{keywords.map(keyword => (
|
||||
<Tag key={keyword} text={keyword} className='mr-2' />
|
||||
<Tag key={keyword} text={keyword} className="mr-2" />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
@ -108,7 +109,7 @@ const ResultItem = ({
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div >
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default React.memo(ResultItem)
|
||||
|
||||
@ -15,12 +15,11 @@ const Score: FC<Props> = ({
|
||||
if (!value || isNaN(value))
|
||||
return null
|
||||
return (
|
||||
<div className={cn('relative items-center overflow-hidden border border-components-progress-bar-border px-[5px]',
|
||||
besideChunkName ? 'h-[20.5px] border-l-0' : 'h-[20px] rounded-md')}>
|
||||
<div className={cn('relative items-center overflow-hidden border border-components-progress-bar-border px-[5px]', besideChunkName ? 'h-[20.5px] border-l-0' : 'h-[20px] rounded-md')}>
|
||||
<div className={cn('absolute left-0 top-0 h-full border-r-[1.5px] border-components-progress-brand-progress bg-util-colors-blue-brand-blue-brand-100', value === 1 && 'border-r-0')} style={{ width: `${value * 100}%` }} />
|
||||
<div className={cn('relative flex h-full items-center space-x-0.5 text-util-colors-blue-brand-blue-brand-700')}>
|
||||
<div className='system-2xs-medium-uppercase'>score</div>
|
||||
<div className='system-xs-semibold'>{value?.toFixed(2)}</div>
|
||||
<div className="system-2xs-medium-uppercase">score</div>
|
||||
<div className="system-xs-semibold">{value?.toFixed(2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,15 +1,5 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import QueryInput from './components/query-input'
|
||||
import s from './style.module.css'
|
||||
import ModifyRetrievalModal from './modify-retrieval-modal'
|
||||
import ResultItem from './components/result-item'
|
||||
import ResultItemExternal from './components/result-item-external'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import type {
|
||||
ExternalKnowledgeBaseHitTesting,
|
||||
ExternalKnowledgeBaseHitTestingResponse,
|
||||
@ -18,22 +8,32 @@ import type {
|
||||
HitTestingResponse,
|
||||
Query,
|
||||
} from '@/models/datasets'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import type { RetrievalConfig } from '@/types/app'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import FloatRightContainer from '@/app/components/base/float-right-container'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Pagination from '@/app/components/base/pagination'
|
||||
import docStyle from '@/app/components/datasets/documents/detail/completed/style.module.css'
|
||||
import { CardSkelton } from '../documents/detail/completed/skeleton/general-list-skeleton'
|
||||
import EmptyRecords from './components/empty-records'
|
||||
import Records from './components/records'
|
||||
import DatasetDetailContext from '@/context/dataset-detail'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { useDatasetTestingRecords } from '@/service/knowledge/use-dataset'
|
||||
import {
|
||||
useExternalKnowledgeBaseHitTesting,
|
||||
useHitTesting,
|
||||
} from '@/service/knowledge/use-hit-testing'
|
||||
import { useDatasetTestingRecords } from '@/service/knowledge/use-dataset'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { CardSkelton } from '../documents/detail/completed/skeleton/general-list-skeleton'
|
||||
import EmptyRecords from './components/empty-records'
|
||||
import QueryInput from './components/query-input'
|
||||
import Records from './components/records'
|
||||
import ResultItem from './components/result-item'
|
||||
import ResultItemExternal from './components/result-item-external'
|
||||
import ModifyRetrievalModal from './modify-retrieval-modal'
|
||||
import s from './style.module.css'
|
||||
|
||||
const limit = 10
|
||||
|
||||
@ -73,32 +73,32 @@ const HitTestingPage: FC<Props> = ({ datasetId }: Props) => {
|
||||
const isRetrievalLoading = isHitTestingPending || isExternalKnowledgeBaseHitTestingPending
|
||||
|
||||
const renderHitResults = (results: HitTesting[] | ExternalKnowledgeBaseHitTesting[]) => (
|
||||
<div className='flex h-full flex-col rounded-tl-2xl bg-background-body px-4 py-3'>
|
||||
<div className='mb-2 shrink-0 pl-2 font-semibold leading-6 text-text-primary'>
|
||||
<div className="flex h-full flex-col rounded-tl-2xl bg-background-body px-4 py-3">
|
||||
<div className="mb-2 shrink-0 pl-2 font-semibold leading-6 text-text-primary">
|
||||
{t('datasetHitTesting.hit.title', { num: results.length })}
|
||||
</div>
|
||||
<div className='grow space-y-2 overflow-y-auto'>
|
||||
<div className="grow space-y-2 overflow-y-auto">
|
||||
{results.map((record, idx) =>
|
||||
isExternal
|
||||
? (
|
||||
<ResultItemExternal
|
||||
key={idx}
|
||||
positionId={idx + 1}
|
||||
payload={record as ExternalKnowledgeBaseHitTesting}
|
||||
/>
|
||||
)
|
||||
<ResultItemExternal
|
||||
key={idx}
|
||||
positionId={idx + 1}
|
||||
payload={record as ExternalKnowledgeBaseHitTesting}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<ResultItem key={idx} payload={record as HitTesting} />
|
||||
),
|
||||
<ResultItem key={idx} payload={record as HitTesting} />
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderEmptyState = () => (
|
||||
<div className='flex h-full flex-col items-center justify-center rounded-tl-2xl bg-background-body px-4 py-3'>
|
||||
<div className="flex h-full flex-col items-center justify-center rounded-tl-2xl bg-background-body px-4 py-3">
|
||||
<div className={cn(docStyle.commonIcon, docStyle.targetIcon, '!h-14 !w-14 !bg-text-quaternary')} />
|
||||
<div className='mt-3 text-[13px] text-text-quaternary'>
|
||||
<div className="mt-3 text-[13px] text-text-quaternary">
|
||||
{t('datasetHitTesting.hit.emptyTip')}
|
||||
</div>
|
||||
</div>
|
||||
@ -115,10 +115,10 @@ const HitTestingPage: FC<Props> = ({ datasetId }: Props) => {
|
||||
|
||||
return (
|
||||
<div className={s.container}>
|
||||
<div className='flex flex-col px-6 py-3'>
|
||||
<div className='mb-4 flex flex-col justify-center'>
|
||||
<h1 className='text-base font-semibold text-text-primary'>{t('datasetHitTesting.title')}</h1>
|
||||
<p className='mt-0.5 text-[13px] font-normal leading-4 text-text-tertiary'>{t('datasetHitTesting.desc')}</p>
|
||||
<div className="flex flex-col px-6 py-3">
|
||||
<div className="mb-4 flex flex-col justify-center">
|
||||
<h1 className="text-base font-semibold text-text-primary">{t('datasetHitTesting.title')}</h1>
|
||||
<p className="mt-0.5 text-[13px] font-normal leading-4 text-text-tertiary">{t('datasetHitTesting.desc')}</p>
|
||||
</div>
|
||||
<QueryInput
|
||||
key={queryInputKey}
|
||||
@ -136,13 +136,13 @@ const HitTestingPage: FC<Props> = ({ datasetId }: Props) => {
|
||||
hitTestingMutation={hitTestingMutation}
|
||||
externalKnowledgeBaseHitTestingMutation={externalKnowledgeBaseHitTestingMutation}
|
||||
/>
|
||||
<div className='mb-3 mt-6 text-base font-semibold text-text-primary'>{t('datasetHitTesting.records')}</div>
|
||||
<div className="mb-3 mt-6 text-base font-semibold text-text-primary">{t('datasetHitTesting.records')}</div>
|
||||
{isRecordsLoading && (
|
||||
<div className='flex-1'><Loading type='app' /></div>
|
||||
<div className="flex-1"><Loading type="app" /></div>
|
||||
)}
|
||||
{!isRecordsLoading && recordsRes?.data && recordsRes.data.length > 0 && (
|
||||
<>
|
||||
<Records records={recordsRes?.data} onClickRecord={handleClickRecord}/>
|
||||
<Records records={recordsRes?.data} onClickRecord={handleClickRecord} />
|
||||
{(total && total > limit)
|
||||
? <Pagination current={currPage} onChange={setCurrPage} total={total} limit={limit} />
|
||||
: null}
|
||||
@ -153,30 +153,31 @@ const HitTestingPage: FC<Props> = ({ datasetId }: Props) => {
|
||||
)}
|
||||
</div>
|
||||
<FloatRightContainer
|
||||
panelClassName='!justify-start !overflow-y-auto'
|
||||
panelClassName="!justify-start !overflow-y-auto"
|
||||
showClose
|
||||
isMobile={isMobile}
|
||||
isOpen={isShowRightPanel}
|
||||
onClose={hideRightPanel}
|
||||
footer={null}
|
||||
>
|
||||
<div className='flex flex-col pt-3'>
|
||||
<div className="flex flex-col pt-3">
|
||||
{isRetrievalLoading
|
||||
? <div className='flex h-full flex-col rounded-tl-2xl bg-background-body px-4 py-3'>
|
||||
<CardSkelton />
|
||||
</div>
|
||||
? (
|
||||
<div className="flex h-full flex-col rounded-tl-2xl bg-background-body px-4 py-3">
|
||||
<CardSkelton />
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
(() => {
|
||||
if (!hitResult?.records.length && !externalHitResult?.records.length)
|
||||
return renderEmptyState()
|
||||
(() => {
|
||||
if (!hitResult?.records.length && !externalHitResult?.records.length)
|
||||
return renderEmptyState()
|
||||
|
||||
if (hitResult?.records.length)
|
||||
return renderHitResults(hitResult.records)
|
||||
if (hitResult?.records.length)
|
||||
return renderHitResults(hitResult.records)
|
||||
|
||||
return renderHitResults(externalHitResult?.records || [])
|
||||
})()
|
||||
)
|
||||
}
|
||||
return renderHitResults(externalHitResult?.records || [])
|
||||
})()
|
||||
)}
|
||||
</div>
|
||||
</FloatRightContainer>
|
||||
<Drawer
|
||||
@ -185,7 +186,7 @@ const HitTestingPage: FC<Props> = ({ datasetId }: Props) => {
|
||||
onClose={() => setIsShowModifyRetrievalModal(false)}
|
||||
footer={null}
|
||||
mask={isMobile}
|
||||
panelClassName='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'
|
||||
panelClassName="mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl"
|
||||
>
|
||||
<ModifyRetrievalModal
|
||||
indexMethod={currentDataset?.indexing_technique || ''}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
RiCloseLine,
|
||||
} from '@remixicon/react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RetrievalSettings from '../external-knowledge-base/create/RetrievalSettings'
|
||||
import Button from '@/app/components/base/button'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Button from '@/app/components/base/button'
|
||||
import RetrievalSettings from '../external-knowledge-base/create/RetrievalSettings'
|
||||
|
||||
type ModifyExternalRetrievalModalProps = {
|
||||
onClose: () => void
|
||||
onSave: (data: { top_k: number; score_threshold: number; score_threshold_enabled: boolean }) => void
|
||||
onSave: (data: { top_k: number, score_threshold: number, score_threshold_enabled: boolean }) => void
|
||||
initialTopK: number
|
||||
initialScoreThreshold: number
|
||||
initialScoreThresholdEnabled: boolean
|
||||
@ -27,7 +27,7 @@ const ModifyExternalRetrievalModal: React.FC<ModifyExternalRetrievalModalProps>
|
||||
const [scoreThreshold, setScoreThreshold] = useState(initialScoreThreshold)
|
||||
const [scoreThresholdEnabled, setScoreThresholdEnabled] = useState(initialScoreThresholdEnabled)
|
||||
|
||||
const handleSettingsChange = (data: { top_k?: number; score_threshold?: number; score_threshold_enabled?: boolean }) => {
|
||||
const handleSettingsChange = (data: { top_k?: number, score_threshold?: number, score_threshold_enabled?: boolean }) => {
|
||||
if (data.top_k !== undefined)
|
||||
setTopK(data.top_k)
|
||||
if (data.score_threshold !== undefined)
|
||||
@ -42,16 +42,16 @@ const ModifyExternalRetrievalModal: React.FC<ModifyExternalRetrievalModalProps>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='shadows-shadow-2xl absolute right-[14px] top-[36px] z-10 flex w-[320px] flex-col items-start rounded-2xl
|
||||
border-[0.5px] border-components-panel-border bg-components-panel-bg'
|
||||
<div className="shadows-shadow-2xl absolute right-[14px] top-[36px] z-10 flex w-[320px] flex-col items-start rounded-2xl
|
||||
border-[0.5px] border-components-panel-border bg-components-panel-bg"
|
||||
>
|
||||
<div className='flex items-center justify-between self-stretch p-4 pb-2'>
|
||||
<div className='system-xl-semibold grow text-text-primary'>{t('datasetHitTesting.settingTitle')}</div>
|
||||
<ActionButton className='ml-auto' onClick={onClose}>
|
||||
<RiCloseLine className='h-4 w-4 shrink-0' />
|
||||
<div className="flex items-center justify-between self-stretch p-4 pb-2">
|
||||
<div className="system-xl-semibold grow text-text-primary">{t('datasetHitTesting.settingTitle')}</div>
|
||||
<ActionButton className="ml-auto" onClick={onClose}>
|
||||
<RiCloseLine className="h-4 w-4 shrink-0" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
<div className='flex flex-col items-start justify-center gap-4 self-stretch p-4 pt-2'>
|
||||
<div className="flex flex-col items-start justify-center gap-4 self-stretch p-4 pt-2">
|
||||
<RetrievalSettings
|
||||
topK={topK}
|
||||
scoreThreshold={scoreThreshold}
|
||||
@ -60,9 +60,9 @@ const ModifyExternalRetrievalModal: React.FC<ModifyExternalRetrievalModalProps>
|
||||
isInHitTesting={true}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex w-full items-end justify-end gap-1 p-4 pt-2'>
|
||||
<Button className='min-w-[72px] shrink-0' onClick={onClose}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant='primary' className='min-w-[72px] shrink-0' onClick={handleSave}>{t('common.operation.save')}</Button>
|
||||
<div className="flex w-full items-end justify-end gap-1 p-4 pt-2">
|
||||
<Button className="min-w-[72px] shrink-0" onClick={onClose}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant="primary" className="min-w-[72px] shrink-0" onClick={handleSave}>{t('common.operation.save')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { IndexingType } from '../create/step-two'
|
||||
import type { RetrievalConfig } from '@/types/app'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
import Toast from '../../base/toast'
|
||||
import { ModelTypeEnum } from '../../header/account-setting/model-provider-page/declarations'
|
||||
import type { RetrievalConfig } from '@/types/app'
|
||||
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
|
||||
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model'
|
||||
import EconomicalRetrievalMethodConfig from '@/app/components/datasets/common/economical-retrieval-method-config'
|
||||
import RetrievalMethodConfig from '@/app/components/datasets/common/retrieval-method-config'
|
||||
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import { checkShowMultiModalTip } from '../settings/utils'
|
||||
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
|
||||
import type { IndexingType } from '../create/step-two'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import Toast from '../../base/toast'
|
||||
import { ModelTypeEnum } from '../../header/account-setting/model-provider-page/declarations'
|
||||
import { checkShowMultiModalTip } from '../settings/utils'
|
||||
|
||||
type Props = {
|
||||
indexMethod: string
|
||||
@ -82,62 +82,62 @@ const ModifyRetrievalModal: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className='flex w-full flex-col rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl shadow-shadow-shadow-9'
|
||||
className="flex w-full flex-col rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl shadow-shadow-shadow-9"
|
||||
style={{
|
||||
height: 'calc(100vh - 72px)',
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
<div className='h-15 flex shrink-0 justify-between px-3 pb-1 pt-3.5'>
|
||||
<div className='text-base font-semibold text-text-primary'>
|
||||
<div className="h-15 flex shrink-0 justify-between px-3 pb-1 pt-3.5">
|
||||
<div className="text-base font-semibold text-text-primary">
|
||||
<div>{t('datasetSettings.form.retrievalSetting.title')}</div>
|
||||
<div className='text-xs font-normal leading-[18px] text-text-tertiary'>
|
||||
<div className="text-xs font-normal leading-[18px] text-text-tertiary">
|
||||
<a
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={docLink('/guides/knowledge-base/retrieval-test-and-citation#modify-text-retrieval-setting', {
|
||||
'zh-Hans': '/guides/knowledge-base/retrieval-test-and-citation#修改文本检索方式',
|
||||
'ja-JP': '/guides/knowledge-base/retrieval-test-and-citation',
|
||||
})}
|
||||
className='text-text-accent'
|
||||
className="text-text-accent"
|
||||
>
|
||||
{t('datasetSettings.form.retrievalSetting.learnMore')}
|
||||
</a>
|
||||
{t('datasetSettings.form.retrievalSetting.description')}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex'>
|
||||
<div className="flex">
|
||||
<div
|
||||
onClick={onHide}
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center'
|
||||
className="flex h-8 w-8 cursor-pointer items-center justify-center"
|
||||
>
|
||||
<RiCloseLine className='h-4 w-4 text-text-tertiary' />
|
||||
<RiCloseLine className="h-4 w-4 text-text-tertiary" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='px-4 py-2'>
|
||||
<div className='mb-1 text-[13px] font-semibold leading-6 text-text-secondary'>
|
||||
<div className="px-4 py-2">
|
||||
<div className="mb-1 text-[13px] font-semibold leading-6 text-text-secondary">
|
||||
{t('datasetSettings.form.retrievalSetting.method')}
|
||||
</div>
|
||||
{indexMethod === 'high_quality'
|
||||
? (
|
||||
<RetrievalMethodConfig
|
||||
value={retrievalConfig}
|
||||
onChange={setRetrievalConfig}
|
||||
showMultiModalTip={showMultiModalTip}
|
||||
/>
|
||||
)
|
||||
<RetrievalMethodConfig
|
||||
value={retrievalConfig}
|
||||
onChange={setRetrievalConfig}
|
||||
showMultiModalTip={showMultiModalTip}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<EconomicalRetrievalMethodConfig
|
||||
value={retrievalConfig}
|
||||
onChange={setRetrievalConfig}
|
||||
/>
|
||||
)}
|
||||
<EconomicalRetrievalMethodConfig
|
||||
value={retrievalConfig}
|
||||
onChange={setRetrievalConfig}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className='flex justify-end p-4 pt-2'>
|
||||
<Button className='mr-2 shrink-0' onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant='primary' className='shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button>
|
||||
<div className="flex justify-end p-4 pt-2">
|
||||
<Button className="mr-2 shrink-0" onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||
<Button variant="primary" className="shrink-0" onClick={handleSave}>{t('common.operation.save')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user