Merge branch 'feat/parent-child-retrieval' of https://github.com/langgenius/dify into feat/parent-child-retrieval

pull/12097/head
AkaraChen 1 year ago
commit 6d689317ea

@ -48,6 +48,11 @@ export const generalResultData: HitTesting[] = [
score: 0.8771945, score: 0.8771945,
content: 'It is quite natural for academics who are continuously told to “publish or perish” to want to always create something from scratch that is their own fresh creation.', content: 'It is quite natural for academics who are continuously told to “publish or perish” to want to always create something from scratch that is their own fresh creation.',
}, },
{
id: '2',
score: 0.5,
content: 'It is quite natural for ',
},
], ],
score: 0.8771945, score: 0.8771945,
tsne_position: null, tsne_position: null,

@ -1,9 +1,8 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { SliceContent } from '../../formatted-text/flavours/shared'
import { SliceContent, SliceLabel } from '../../formatted-text/flavours/shared' import Score from './score'
import cn from '@/utils/classnames'
import type { HitTestingChildChunk } from '@/models/datasets' import type { HitTestingChildChunk } from '@/models/datasets'
type Props = { type Props = {
@ -15,16 +14,16 @@ const ChildChunks: FC<Props> = ({
payload, payload,
isShowAll, isShowAll,
}) => { }) => {
const { t } = useTranslation()
const { id, score, content } = payload const { id, score, content } = payload
return ( return (
<div className='flex items-center space-x-2'> <div
<SliceLabel> className={!isShowAll ? 'line-clamp-2' : ''}
{id} {score} >
</SliceLabel> <div className='inline-flex'>
<SliceContent className={cn(!isShowAll && 'line-clamp-2')}> <div className='bg-state-accent-solid system-2xs-semibold-uppercase px-1'>C-{id}</div>
{content} <Score value={score} />
</SliceContent> </div>
<SliceContent className='bg-state-accent-hover group-hover:bg-state-accent-hover'>{content}</SliceContent>
</div> </div>
) )
} }

@ -13,6 +13,8 @@ import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag' import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
const i18nPrefix = 'datasetHitTesting'
type Props = { type Props = {
payload: HitTesting payload: HitTesting
onHide: () => void onHide: () => void
@ -24,19 +26,19 @@ const ChunkDetailModal: FC<Props> = ({
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { segment, score, child_chunks } = payload const { segment, score, child_chunks } = payload
const { position, word_count, content, keywords, document } = segment const { position, content, keywords, document } = segment
const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0) const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
const extension = document.name.split('.').slice(0, -1)[0] as FileAppearanceTypeEnum const extension = document.name.split('.').slice(0, -1)[0] as FileAppearanceTypeEnum
const maxHeighClassName = 'max-h-[752px] overflow-y-auto'
return ( return (
<Modal <Modal
title={t('dataset.chunkDetail')} title={t(`${i18nPrefix}.chunkDetail`)}
isShow isShow
closable closable
onClose={onHide} onClose={onHide}
className={cn(isParentChildRetrieval ? '!min-w-[1200px]' : '!min-w-[720px]')} className={cn(isParentChildRetrieval ? '!min-w-[1200px]' : '!min-w-[720px]')}
> >
<div className='flex h-'> <div className='flex pb-6'>
<div> <div>
{/* Meta info */} {/* Meta info */}
<div className='flex justify-between items-center'> <div className='flex justify-between items-center'>
@ -54,12 +56,12 @@ const ChunkDetailModal: FC<Props> = ({
</div> </div>
<Score value={score} /> <Score value={score} />
</div> </div>
<div className=' max-h-[752px] overflow-y-auto'> <div className={cn('mt-2 body-md-regular text-text-secondary', maxHeighClassName)}>
{content} {content}
</div> </div>
{!isParentChildRetrieval && keywords && keywords.length > 0 && ( {!isParentChildRetrieval && keywords && keywords.length > 0 && (
<div> <div className='mt-6'>
<div>{t('dataset.keywords')}</div> <div className='font-medium text-xs text-text-tertiary uppercase'>{t(`${i18nPrefix}.keyword`)}</div>
<div className='flex flex-wrap'> <div className='flex flex-wrap'>
{keywords.map(keyword => ( {keywords.map(keyword => (
<Tag key={keyword} text={keyword} className='mr-2' /> <Tag key={keyword} text={keyword} className='mr-2' />
@ -71,8 +73,8 @@ const ChunkDetailModal: FC<Props> = ({
{isParentChildRetrieval && ( {isParentChildRetrieval && (
<div className='shrink-0 w-[552px] px-6'> <div className='shrink-0 w-[552px] px-6'>
<div>{t('dataset.hitChunks', { num: child_chunks.length })}</div> <div className='system-xs-semibold-uppercase text-text-secondary'>{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}</div>
<div className='space-y-2'> <div className={cn('mt-1 space-y-2', maxHeighClassName)}>
{child_chunks.map(item => ( {child_chunks.map(item => (
<ChildChunksItem key={item.id} payload={item} isShowAll /> <ChildChunksItem key={item.id} payload={item} isShowAll />
))} ))}

@ -15,6 +15,7 @@ import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types' import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag' import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
const i18nPrefix = 'datasetHitTesting'
type Props = { type Props = {
payload: HitTesting payload: HitTesting
} }
@ -54,17 +55,21 @@ const ResultItem: FC<Props> = ({
</div> </div>
{/* Main */} {/* Main */}
<div className='px-3'> <div className='mt-1 px-3'>
<div className='line-clamp-2'>{content}</div> <div className='line-clamp-2 body-md-regular'>{content}</div>
{isParentChildRetrieval && ( {isParentChildRetrieval && (
<div> <div className='mt-1'>
<div className='flex items-center space-x-0.5 text-text-secondary' onClick={toggleFold}> <div className='flex items-center space-x-0.5 text-text-secondary' onClick={toggleFold}>
<Icon className={cn('w-4 h-4', isFold && 'opacity-50')} /> <Icon className={cn('w-4 h-4', isFold && 'opacity-50')} />
<div>{t('dataset.hitChunks', { num: child_chunks.length })}</div> <div>{t(`${i18nPrefix}.dataset.hitChunks`, { num: child_chunks.length })}</div>
</div>
<div className='space-y-2'>
{child_chunks.map(item => (
<div key={item.id} className='ml-[7px] pl-[7px] border-l-[2px] border-text-accent-secondary'>
<ChildChunkItem payload={item} isShowAll={false} />
</div>
))}
</div> </div>
{child_chunks.map(item => (
<ChildChunkItem key={item.id} payload={item} isShowAll={false} />
))}
</div> </div>
)} )}
{!isParentChildRetrieval && keywords && keywords.length > 0 && ( {!isParentChildRetrieval && keywords && keywords.length > 0 && (
@ -76,7 +81,7 @@ const ResultItem: FC<Props> = ({
)} )}
</div> </div>
{/* Foot */} {/* Foot */}
<div className='flex justify-between items-center h-10 pl-3 pr-2 border-t border-divider-subtle'> <div className='mt-3 flex justify-between items-center h-10 pl-3 pr-2 border-t border-divider-subtle'>
<div className='flex items-center space-x-1'> <div className='flex items-center space-x-1'>
<FileIcon type={extension} size='sm' /> <FileIcon type={extension} size='sm' />
<span className='grow w-0 truncate text-text-secondary text-[13px] font-normal'>{document.name}</span> <span className='grow w-0 truncate text-text-secondary text-[13px] font-normal'>{document.name}</span>
@ -85,7 +90,7 @@ const ResultItem: FC<Props> = ({
className='flex items-center space-x-1 cursor-pointer text-text-tertiary' className='flex items-center space-x-1 cursor-pointer text-text-tertiary'
onClick={showDetailModal} onClick={showDetailModal}
> >
<div className='text-xs uppercase'>{t('dataset.open')}</div> <div className='text-xs uppercase'>{t(`${i18nPrefix}.open`)}</div>
<RiArrowRightUpLine className='size-3.5' /> <RiArrowRightUpLine className='size-3.5' />
</div> </div>
</div> </div>

@ -1,18 +1,21 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React from 'react' import React from 'react'
import cn from '@/utils/classnames'
type Props = { type Props = {
value: number value: number
besideChunkName?: boolean
} }
const Score: FC<Props> = ({ const Score: FC<Props> = ({
value, value,
besideChunkName,
}) => { }) => {
return ( return (
<div className='relative items-center px-[5px] rounded-md border border-components-progress-bar-border overflow-hidden'> <div className={cn('relative items-center px-[5px] border border-components-progress-bar-border overflow-hidden', besideChunkName ? 'border-l-0' : 'rounded-md')}>
<div className='absolute top-0 left-0 h-full bg-util-colors-blue-brand-blue-brand-100 border-r-[1.5px] border-components-progress-brand-progress ' style={{ width: `${value * 100}%` }} /> <div className='absolute top-0 left-0 h-full bg-util-colors-blue-brand-blue-brand-100 border-r-[1.5px] border-components-progress-brand-progress ' style={{ width: `${value * 100}%` }} />
<div className='relative flex items-center h-4 space-x-0.5 text-util-colors-blue-brand-blue-brand-700'> <div className={cn('relative flex items-center h-5 space-x-0.5 text-util-colors-blue-brand-blue-brand-700')}>
<div className='system-2xs-medium-uppercase'>score</div> <div className='system-2xs-medium-uppercase'>score</div>
<div className='system-xs-semibold'>{value.toFixed(2)}</div> <div className='system-xs-semibold'>{value.toFixed(2)}</div>
</div> </div>

@ -25,6 +25,10 @@ const translation = {
noRecentTip: 'No recent query results here', noRecentTip: 'No recent query results here',
viewChart: 'View VECTOR CHART', viewChart: 'View VECTOR CHART',
viewDetail: 'View Detail', viewDetail: 'View Detail',
chunkDetail: 'Chunk Detail',
hitChunks: 'Hit {{num}} child chunks',
open: 'Open',
keyword: 'Keywords',
} }
export default translation export default translation

@ -25,6 +25,10 @@ const translation = {
noRecentTip: '最近无查询结果', noRecentTip: '最近无查询结果',
viewChart: '查看向量图表', viewChart: '查看向量图表',
viewDetail: '查看详情', viewDetail: '查看详情',
chunkDetail: '段落详情',
hitChunks: '命中 {{num}} 个子段落',
open: '打开',
keyword: '关键词',
} }
export default translation export default translation

Loading…
Cancel
Save