Compare commits

...

4 Commits

Author SHA1 Message Date
zxhlyh
01a7dbcee8 Merge branch 'main' into feat/summary-index 2026-01-13 16:29:09 +08:00
zxhlyh
4fe8d2491e feat: summary index 2026-01-13 16:27:32 +08:00
zxhlyh
5c2ae922bc merge main 2026-01-12 13:42:17 +08:00
zxhlyh
13eec13a14 feat: summary index 2026-01-12 13:38:18 +08:00
31 changed files with 644 additions and 14 deletions

View File

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 7.33337V2.66671H4.00002V13.3334H8.00002C8.36821 13.3334 8.66669 13.6319 8.66669 14C8.66669 14.3682 8.36821 14.6667 8.00002 14.6667H3.33335C2.96516 14.6667 2.66669 14.3682 2.66669 14V2.00004C2.66669 1.63185 2.96516 1.33337 3.33335 1.33337H12.6667C13.0349 1.33337 13.3334 1.63185 13.3334 2.00004V7.33337C13.3334 7.70156 13.0349 8.00004 12.6667 8.00004C12.2985 8.00004 12 7.70156 12 7.33337Z" fill="#354052"/>
<path d="M10 4.00004C10.3682 4.00004 10.6667 4.29852 10.6667 4.66671C10.6667 5.0349 10.3682 5.33337 10 5.33337H6.00002C5.63183 5.33337 5.33335 5.0349 5.33335 4.66671C5.33335 4.29852 5.63183 4.00004 6.00002 4.00004H10Z" fill="#354052"/>
<path d="M8.00002 6.66671C8.36821 6.66671 8.66669 6.96518 8.66669 7.33337C8.66669 7.70156 8.36821 8.00004 8.00002 8.00004H6.00002C5.63183 8.00004 5.33335 7.70156 5.33335 7.33337C5.33335 6.96518 5.63183 6.66671 6.00002 6.66671H8.00002Z" fill="#354052"/>
<path d="M12.827 10.7902L12.3624 9.58224C12.3048 9.43231 12.1607 9.33337 12 9.33337C11.8394 9.33337 11.6953 9.43231 11.6376 9.58224L11.173 10.7902C11.1054 10.9662 10.9662 11.1054 10.7902 11.173L9.58222 11.6376C9.43229 11.6953 9.33335 11.8394 9.33335 12C9.33335 12.1607 9.43229 12.3048 9.58222 12.3624L10.7902 12.827C10.9662 12.8947 11.1054 13.0338 11.173 13.2099L11.6376 14.4178C11.6953 14.5678 11.8394 14.6667 12 14.6667C12.1607 14.6667 12.3048 14.5678 12.3624 14.4178L12.827 13.2099C12.8947 13.0338 13.0338 12.8947 13.2099 12.827L14.4178 12.3624C14.5678 12.3048 14.6667 12.1607 14.6667 12C14.6667 11.8394 14.5678 11.6953 14.4178 11.6376L13.2099 11.173C13.0338 11.1054 12.8947 10.9662 12.827 10.7902Z" fill="#354052"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,53 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M12 7.33337V2.66671H4.00002V13.3334H8.00002C8.36821 13.3334 8.66669 13.6319 8.66669 14C8.66669 14.3682 8.36821 14.6667 8.00002 14.6667H3.33335C2.96516 14.6667 2.66669 14.3682 2.66669 14V2.00004C2.66669 1.63185 2.96516 1.33337 3.33335 1.33337H12.6667C13.0349 1.33337 13.3334 1.63185 13.3334 2.00004V7.33337C13.3334 7.70156 13.0349 8.00004 12.6667 8.00004C12.2985 8.00004 12 7.70156 12 7.33337Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M10 4.00004C10.3682 4.00004 10.6667 4.29852 10.6667 4.66671C10.6667 5.0349 10.3682 5.33337 10 5.33337H6.00002C5.63183 5.33337 5.33335 5.0349 5.33335 4.66671C5.33335 4.29852 5.63183 4.00004 6.00002 4.00004H10Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M8.00002 6.66671C8.36821 6.66671 8.66669 6.96518 8.66669 7.33337C8.66669 7.70156 8.36821 8.00004 8.00002 8.00004H6.00002C5.63183 8.00004 5.33335 7.70156 5.33335 7.33337C5.33335 6.96518 5.63183 6.66671 6.00002 6.66671H8.00002Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M12.827 10.7902L12.3624 9.58224C12.3048 9.43231 12.1607 9.33337 12 9.33337C11.8394 9.33337 11.6953 9.43231 11.6376 9.58224L11.173 10.7902C11.1054 10.9662 10.9662 11.1054 10.7902 11.173L9.58222 11.6376C9.43229 11.6953 9.33335 11.8394 9.33335 12C9.33335 12.1607 9.43229 12.3048 9.58222 12.3624L10.7902 12.827C10.9662 12.8947 11.1054 13.0338 11.173 13.2099L11.6376 14.4178C11.6953 14.5678 11.8394 14.6667 12 14.6667C12.1607 14.6667 12.3048 14.5678 12.3624 14.4178L12.827 13.2099C12.8947 13.0338 13.0338 12.8947 13.2099 12.827L14.4178 12.3624C14.5678 12.3048 14.6667 12.1607 14.6667 12C14.6667 11.8394 14.5678 11.6953 14.4178 11.6376L13.2099 11.173C13.0338 11.1054 12.8947 10.9662 12.827 10.7902Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "SearchLinesSparkle"
}

View File

@@ -0,0 +1,20 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import type { IconData } from '@/app/components/base/icons/IconBase'
import * as React from 'react'
import IconBase from '@/app/components/base/icons/IconBase'
import data from './SearchLinesSparkle.json'
const Icon = (
{
ref,
...props
}: React.SVGProps<SVGSVGElement> & {
ref?: React.RefObject<React.RefObject<HTMLOrSVGElement>>
},
) => <IconBase {...props} ref={ref} data={data as IconData} />
Icon.displayName = 'SearchLinesSparkle'
export default Icon

View File

@@ -11,5 +11,6 @@ export { default as HighQuality } from './HighQuality'
export { default as HybridSearch } from './HybridSearch'
export { default as ParentChildChunk } from './ParentChildChunk'
export { default as QuestionAndAnswer } from './QuestionAndAnswer'
export { default as SearchLinesSparkle } from './SearchLinesSparkle'
export { default as SearchMenu } from './SearchMenu'
export { default as VectorSearch } from './VectorSearch'

View File

@@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
import type { PreProcessingRule } from '@/models/datasets'
import type { PreProcessingRule, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import {
RiAlertFill,
RiSearchEyeLine,
@@ -12,6 +12,7 @@ import Button from '@/app/components/base/button'
import Checkbox from '@/app/components/base/checkbox'
import Divider from '@/app/components/base/divider'
import Tooltip from '@/app/components/base/tooltip'
import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting'
import { IS_CE_EDITION } from '@/config'
import { ChunkingMode } from '@/models/datasets'
import SettingCog from '../../assets/setting-gear-mod.svg'
@@ -52,6 +53,8 @@ type GeneralChunkingOptionsProps = {
onReset: () => void
// Locale
locale: string
summaryIndexSetting?: SummaryIndexSettingType
onSummaryIndexSettingChange?: (payload: SummaryIndexSettingType) => void
}
export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
@@ -74,6 +77,8 @@ export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
onPreview,
onReset,
locale,
summaryIndexSetting,
onSummaryIndexSettingChange,
}) => {
const { t } = useTranslation()
@@ -146,6 +151,13 @@ export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
</label>
</div>
))}
<div className="mt-3">
<SummaryIndexSetting
entry="create-document"
summaryIndexSetting={summaryIndexSetting}
onSummaryIndexSettingChange={onSummaryIndexSettingChange}
/>
</div>
{IS_CE_EDITION && (
<>
<Divider type="horizontal" className="my-4 bg-divider-subtle" />

View File

@@ -2,7 +2,7 @@
import type { FC } from 'react'
import type { ParentChildConfig } from '../hooks'
import type { ParentMode, PreProcessingRule } from '@/models/datasets'
import type { ParentMode, PreProcessingRule, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import { RiSearchEyeLine } from '@remixicon/react'
import Image from 'next/image'
import { useTranslation } from 'react-i18next'
@@ -11,6 +11,7 @@ import Checkbox from '@/app/components/base/checkbox'
import Divider from '@/app/components/base/divider'
import { ParentChildChunk } from '@/app/components/base/icons/src/vender/knowledge'
import RadioCard from '@/app/components/base/radio-card'
import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting'
import { ChunkingMode } from '@/models/datasets'
import FileList from '../../assets/file-list-3-fill.svg'
import Note from '../../assets/note-mod.svg'
@@ -31,6 +32,8 @@ type ParentChildOptionsProps = {
// State
parentChildConfig: ParentChildConfig
rules: PreProcessingRule[]
summaryIndexSetting?: SummaryIndexSettingType
onSummaryIndexSettingChange?: (payload: SummaryIndexSettingType) => void
currentDocForm: ChunkingMode
// Flags
isActive: boolean
@@ -51,6 +54,7 @@ type ParentChildOptionsProps = {
export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
parentChildConfig,
rules,
summaryIndexSetting,
currentDocForm: _currentDocForm,
isActive,
isInUpload,
@@ -62,6 +66,7 @@ export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
onChildDelimiterChange,
onChildMaxLengthChange,
onRuleToggle,
onSummaryIndexSettingChange,
onPreview,
onReset,
}) => {
@@ -183,6 +188,13 @@ export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
</label>
</div>
))}
<div className="mt-3">
<SummaryIndexSetting
entry="create-document"
summaryIndexSetting={summaryIndexSetting}
onSummaryIndexSettingChange={onSummaryIndexSettingChange}
/>
</div>
</div>
</div>
</div>

View File

@@ -9,6 +9,7 @@ import type {
CustomFile,
FullDocumentDetail,
ProcessRule,
SummaryIndexSetting as SummaryIndexSettingType,
} from '@/models/datasets'
import type { RetrievalConfig, RETRIEVE_METHOD } from '@/types/app'
import { useCallback } from 'react'
@@ -141,6 +142,7 @@ export const useDocumentCreation = (options: UseDocumentCreationOptions) => {
retrievalConfig: RetrievalConfig,
embeddingModel: DefaultModel,
indexingTechnique: string,
summaryIndexSetting?: SummaryIndexSettingType,
): CreateDocumentReq | null => {
if (isSetting) {
return {
@@ -148,6 +150,7 @@ export const useDocumentCreation = (options: UseDocumentCreationOptions) => {
doc_form: currentDocForm,
doc_language: docLanguage,
process_rule: processRule,
summary_index_setting: summaryIndexSetting,
retrieval_model: retrievalConfig,
embedding_model: embeddingModel.model,
embedding_model_provider: embeddingModel.provider,
@@ -164,6 +167,7 @@ export const useDocumentCreation = (options: UseDocumentCreationOptions) => {
},
indexing_technique: indexingTechnique,
process_rule: processRule,
summary_index_setting: summaryIndexSetting,
doc_form: currentDocForm,
doc_language: docLanguage,
retrieval_model: retrievalConfig,

View File

@@ -1,4 +1,5 @@
import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
import { useEffect, useMemo, useState } from 'react'
import { checkShowMultiModalTip } from '@/app/components/datasets/settings/utils'
@@ -29,6 +30,7 @@ export type UseIndexingConfigOptions = {
initialRetrievalConfig?: RetrievalConfig
isAPIKeySet: boolean
hasSetIndexType: boolean
initialSummaryIndexSetting?: SummaryIndexSettingType
}
export const useIndexingConfig = (options: UseIndexingConfigOptions) => {
@@ -38,6 +40,7 @@ export const useIndexingConfig = (options: UseIndexingConfigOptions) => {
initialRetrievalConfig,
isAPIKeySet,
hasSetIndexType,
initialSummaryIndexSetting,
} = options
// Rerank model
@@ -115,6 +118,11 @@ export const useIndexingConfig = (options: UseIndexingConfigOptions) => {
// Get effective indexing technique
const getIndexingTechnique = () => initialIndexType || indexType
// Summary index setting
const [summaryIndexSetting, setSummaryIndexSetting] = useState<SummaryIndexSettingType | undefined>(
initialSummaryIndexSetting ?? undefined,
)
return {
// Index type
indexType,
@@ -137,6 +145,10 @@ export const useIndexingConfig = (options: UseIndexingConfigOptions) => {
// Computed
showMultiModalTip,
// Summary index setting
summaryIndexSetting,
setSummaryIndexSetting,
}
}

View File

@@ -72,6 +72,7 @@ const StepTwo: FC<StepTwoProps> = ({
initialRetrievalConfig: currentDataset?.retrieval_model_dict,
isAPIKeySet,
hasSetIndexType,
initialSummaryIndexSetting: currentDataset?.summary_index_setting,
})
const preview = usePreviewState({ dataSourceType, files, notionPages, websitePages, documentDetail, datasetId })
const creation = useDocumentCreation({
@@ -156,7 +157,7 @@ const StepTwo: FC<StepTwoProps> = ({
})
if (!isValid)
return
const params = creation.buildCreationParams(currentDocForm, docLanguage, segmentation.getProcessRule(currentDocForm), indexing.retrievalConfig, indexing.embeddingModel, indexing.getIndexingTechnique())
const params = creation.buildCreationParams(currentDocForm, docLanguage, segmentation.getProcessRule(currentDocForm), indexing.retrievalConfig, indexing.embeddingModel, indexing.getIndexingTechnique(), indexing.summaryIndexSetting)
if (!params)
return
await creation.executeCreation(params, indexing.indexType, indexing.retrievalConfig)
@@ -217,6 +218,8 @@ const StepTwo: FC<StepTwoProps> = ({
onPreview={updatePreview}
onReset={segmentation.resetToDefaults}
locale={locale}
summaryIndexSetting={indexing.summaryIndexSetting}
onSummaryIndexSettingChange={indexing.setSummaryIndexSetting}
/>
)}
{showParentChildOption && (
@@ -236,6 +239,8 @@ const StepTwo: FC<StepTwoProps> = ({
onRuleToggle={segmentation.toggleRule}
onPreview={updatePreview}
onReset={segmentation.resetToDefaults}
summaryIndexSetting={indexing.summaryIndexSetting}
onSummaryIndexSettingChange={indexing.setSummaryIndexSetting}
/>
)}
<Divider className="my-5" />

View File

@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Confirm from '@/app/components/base/confirm'
import Divider from '@/app/components/base/divider'
import { SearchLinesSparkle } from '@/app/components/base/icons/src/vender/knowledge'
import { cn } from '@/utils/classnames'
const i18nPrefix = 'batchAction'
@@ -15,6 +16,7 @@ type IBatchActionProps = {
onBatchEnable: () => void
onBatchDisable: () => void
onBatchDelete: () => Promise<void>
onBatchSummary?: () => void
onArchive?: () => void
onEditMetadata?: () => void
onBatchReIndex?: () => void
@@ -26,6 +28,7 @@ const BatchAction: FC<IBatchActionProps> = ({
selectedIds,
onBatchEnable,
onBatchDisable,
onBatchSummary,
onArchive,
onBatchDelete,
onEditMetadata,
@@ -82,7 +85,16 @@ const BatchAction: FC<IBatchActionProps> = ({
<span className="px-0.5">{t('metadata.metadata', { ns: 'dataset' })}</span>
</Button>
)}
{onBatchSummary && (
<Button
variant="ghost"
className="gap-x-0.5 px-3"
onClick={onBatchSummary}
>
<SearchLinesSparkle className="size-4" />
<span className="px-0.5">{t('list.action.summary', { ns: 'datasetDocuments' })}</span>
</Button>
)}
{onArchive && (
<Button
variant="ghost"

View File

@@ -0,0 +1,26 @@
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
type SummaryLabelProps = {
summary?: string
className?: string
}
const SummaryLabel = ({
summary,
className,
}: SummaryLabelProps) => {
const { t } = useTranslation()
return (
<div className={cn('space-y-1', className)}>
<div className="system-xs-medium-uppercase mt-2 flex items-center justify-between text-text-tertiary">
{t('segment.summary', { ns: 'datasetDocuments' })}
<div className="ml-2 h-px grow bg-divider-regular"></div>
</div>
<div className="body-xs-regular text-text-tertiary">{summary}</div>
</div>
)
}
export default memo(SummaryLabel)

View File

@@ -0,0 +1,47 @@
import { memo, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge'
import { SearchLinesSparkle } from '@/app/components/base/icons/src/vender/knowledge'
import Tooltip from '@/app/components/base/tooltip'
type SummaryStatusProps = {
status: string
}
const SummaryStatus = ({ status }: SummaryStatusProps) => {
const { t } = useTranslation()
const tip = useMemo(() => {
if (status === 'COMPLETED') {
return t('list.summary.ready', { ns: 'datasetDocuments' })
}
if (status === 'GENERATING') {
return t('list.summary.generatingSummary', { ns: 'datasetDocuments' })
}
return ''
}, [status, t])
return (
<Tooltip
popupContent={tip}
>
{
status === 'COMPLETED' && (
<Badge>
<SearchLinesSparkle className="h-3 w-3" />
</Badge>
)
}
{
status === 'GENERATING' && (
<Badge className="border-text-accent-secondary text-text-accent-secondary">
<SearchLinesSparkle className="mr-0.5 h-3 w-3" />
<span>{t('list.summary.generating', { ns: 'datasetDocuments' })}</span>
</Badge>
)
}
</Tooltip>
)
}
export default memo(SummaryStatus)

View File

@@ -0,0 +1,35 @@
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import Textarea from 'react-textarea-autosize'
import { cn } from '@/utils/classnames'
type SummaryTextProps = {
value?: string
onChange?: (value: string) => void
disabled?: boolean
}
const SummaryText = ({
value,
onChange,
disabled,
}: SummaryTextProps) => {
const { t } = useTranslation()
return (
<div className="space-y-1">
<div className="system-xs-medium-uppercase text-text-tertiary">{t('segment.summary', { ns: 'datasetDocuments' })}</div>
<Textarea
className={cn(
'body-sm-regular w-full resize-none bg-transparent leading-6 text-text-secondary outline-none',
)}
placeholder={t('segment.summaryPlaceholder', { ns: 'datasetDocuments' })}
minRows={1}
value={value ?? ''}
onChange={e => onChange?.(e.target.value)}
disabled={disabled}
/>
</div>
)
}
export default memo(SummaryText)

View File

@@ -322,6 +322,7 @@ const Completed: FC<ICompletedProps> = ({
answer: string,
keywords: string[],
attachments: FileEntity[],
summary?: string,
needRegenerate = false,
) => {
const params: SegmentUpdater = { content: '', attachment_ids: [] }
@@ -351,6 +352,9 @@ const Completed: FC<ICompletedProps> = ({
params.attachment_ids = attachments.map(item => item.uploadedId!)
}
if (summary)
params.summary = summary
if (needRegenerate)
params.regenerate_child_chunks = needRegenerate
@@ -364,6 +368,7 @@ const Completed: FC<ICompletedProps> = ({
if (seg.id === segmentId) {
seg.answer = res.data.answer
seg.content = res.data.content
seg.summary = res.data.summary
seg.sign_content = res.data.sign_content
seg.keywords = res.data.keywords
seg.attachments = res.data.attachments

View File

@@ -19,13 +19,14 @@ import { useDocumentContext } from '../../context'
import ChildSegmentList from '../child-segment-list'
import Dot from '../common/dot'
import { SegmentIndexTag } from '../common/segment-index-tag'
import SummaryLabel from '../common/summary-label'
import Tag from '../common/tag'
import ParentChunkCardSkeleton from '../skeleton/parent-chunk-card-skeleton'
import ChunkContent from './chunk-content'
type ISegmentCardProps = {
loading: boolean
detail?: SegmentDetailModel & { document?: { name: string } }
detail?: SegmentDetailModel & { document?: { name: string }, status?: string }
onClick?: () => void
onChangeSwitch?: (enabled: boolean, segId?: string) => Promise<void>
onDelete?: (segId: string) => Promise<void>
@@ -43,7 +44,7 @@ type ISegmentCardProps = {
}
const SegmentCard: FC<ISegmentCardProps> = ({
detail = {},
detail = { status: '' },
onClick,
onChangeSwitch,
onDelete,
@@ -67,6 +68,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
word_count,
hit_count,
answer,
summary,
keywords,
child_chunks = [],
created_at,
@@ -237,6 +239,11 @@ const SegmentCard: FC<ISegmentCardProps> = ({
className={contentOpacity}
/>
{images.length > 0 && <ImageList images={images} size="md" className="py-1" />}
{
summary && (
<SummaryLabel summary={summary} className="mt-2" />
)
}
{isGeneralMode && (
<div className={cn('flex flex-wrap items-center gap-2 py-1.5', contentOpacity)}>
{keywords?.map(keyword => <Tag key={keyword} text={keyword} />)}

View File

@@ -25,6 +25,7 @@ import Dot from './common/dot'
import Keywords from './common/keywords'
import RegenerationModal from './common/regeneration-modal'
import { SegmentIndexTag } from './common/segment-index-tag'
import SummaryText from './common/summary-text'
import { useSegmentListContext } from './index'
type ISegmentDetailProps = {
@@ -35,6 +36,7 @@ type ISegmentDetailProps = {
a: string,
k: string[],
attachments: FileEntity[],
summary?: string,
needRegenerate?: boolean,
) => void
onCancel: () => void
@@ -57,6 +59,7 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
const { t } = useTranslation()
const [question, setQuestion] = useState(isEditMode ? segInfo?.content || '' : segInfo?.sign_content || '')
const [answer, setAnswer] = useState(segInfo?.answer || '')
const [summary, setSummary] = useState(segInfo?.summary || '')
const [attachments, setAttachments] = useState<FileEntity[]>(() => {
return segInfo?.attachments?.map(item => ({
id: uuid4(),
@@ -91,8 +94,8 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
}, [onCancel])
const handleSave = useCallback(() => {
onUpdate(segInfo?.id || '', question, answer, keywords, attachments)
}, [onUpdate, segInfo?.id, question, answer, keywords, attachments])
onUpdate(segInfo?.id || '', question, answer, keywords, attachments, summary, false)
}, [onUpdate, segInfo?.id, question, answer, keywords, attachments, summary])
const handleRegeneration = useCallback(() => {
setShowRegenerationModal(true)
@@ -111,8 +114,8 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
}, [onCancel, onModalStateChange])
const onConfirmRegeneration = useCallback(() => {
onUpdate(segInfo?.id || '', question, answer, keywords, attachments, true)
}, [onUpdate, segInfo?.id, question, answer, keywords, attachments])
onUpdate(segInfo?.id || '', question, answer, keywords, attachments, summary, true)
}, [onUpdate, segInfo?.id, question, answer, keywords, attachments, summary])
const onAttachmentsChange = useCallback((attachments: FileEntity[]) => {
setAttachments(attachments)
@@ -197,6 +200,11 @@ const SegmentDetail: FC<ISegmentDetailProps> = ({
value={attachments}
onChange={onAttachmentsChange}
/>
<SummaryText
value={summary}
onChange={summary => setSummary(summary)}
disabled={!isEditMode}
/>
{isECOIndexing && (
<Keywords
className="w-full"

View File

@@ -27,7 +27,7 @@ import { useDatasetDetailContextWithSelector as useDatasetDetailContext } from '
import useTimestamp from '@/hooks/use-timestamp'
import { ChunkingMode, DataSourceType, DocumentActionType } from '@/models/datasets'
import { DatasourceType } from '@/models/pipeline'
import { useDocumentArchive, useDocumentBatchRetryIndex, useDocumentDelete, useDocumentDisable, useDocumentEnable } from '@/service/knowledge/use-document'
import { useDocumentArchive, useDocumentBatchRetryIndex, useDocumentDelete, useDocumentDisable, useDocumentEnable, useDocumentSummary } from '@/service/knowledge/use-document'
import { asyncRunSafe } from '@/utils'
import { cn } from '@/utils/classnames'
import { formatNumber } from '@/utils/format'
@@ -35,6 +35,7 @@ import FileTypeIcon from '../../base/file-uploader/file-type-icon'
import ChunkingModeLabel from '../common/chunking-mode-label'
import useBatchEditDocumentMetadata from '../metadata/hooks/use-batch-edit-document-metadata'
import BatchAction from './detail/completed/common/batch-action'
import SummaryStatus from './detail/completed/common/summary-status'
import Operations from './operations'
import RenameModal from './rename-modal'
import StatusItem from './status-item'
@@ -218,6 +219,7 @@ const DocumentList: FC<IDocumentListProps> = ({
onSelectedIdChange(uniq([...selectedIds, ...localDocs.map(doc => doc.id)]))
}, [isAllSelected, localDocs, onSelectedIdChange, selectedIds])
const { mutateAsync: archiveDocument } = useDocumentArchive()
const { mutateAsync: generateSummary } = useDocumentSummary()
const { mutateAsync: enableDocument } = useDocumentEnable()
const { mutateAsync: disableDocument } = useDocumentDisable()
const { mutateAsync: deleteDocument } = useDocumentDelete()
@@ -230,6 +232,9 @@ const DocumentList: FC<IDocumentListProps> = ({
case DocumentActionType.archive:
opApi = archiveDocument
break
case DocumentActionType.summary:
opApi = generateSummary
break
case DocumentActionType.enable:
opApi = enableDocument
break
@@ -409,6 +414,13 @@ const DocumentList: FC<IDocumentListProps> = ({
>
<span className="grow-1 truncate text-sm">{doc.name}</span>
</Tooltip>
{
doc.summary_index_status && (
<div className="ml-1 hidden shrink-0 group-hover:flex">
<SummaryStatus status={doc.summary_index_status} />
</div>
)
}
<div className="hidden shrink-0 group-hover:ml-auto group-hover:flex">
<Tooltip
popupContent={t('list.table.rename', { ns: 'datasetDocuments' })}
@@ -461,6 +473,7 @@ const DocumentList: FC<IDocumentListProps> = ({
className="absolute bottom-16 left-0 z-20"
selectedIds={selectedIds}
onArchive={handleAction(DocumentActionType.archive)}
onBatchSummary={handleAction(DocumentActionType.summary)}
onBatchEnable={handleAction(DocumentActionType.enable)}
onBatchDisable={handleAction(DocumentActionType.disable)}
onBatchDelete={handleAction(DocumentActionType.delete)}

View File

@@ -17,6 +17,7 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { SearchLinesSparkle } from '@/app/components/base/icons/src/vender/knowledge'
import { DataSourceType, DocumentActionType } from '@/models/datasets'
import {
useDocumentArchive,
@@ -25,6 +26,7 @@ import {
useDocumentEnable,
useDocumentPause,
useDocumentResume,
useDocumentSummary,
useDocumentUnArchive,
useSyncDocument,
useSyncWebsite,
@@ -82,6 +84,7 @@ const Operations = ({
const { mutateAsync: deleteDocument } = useDocumentDelete()
const { mutateAsync: syncDocument } = useSyncDocument()
const { mutateAsync: syncWebsite } = useSyncWebsite()
const { mutateAsync: generateSummary } = useDocumentSummary()
const { mutateAsync: pauseDocument } = useDocumentPause()
const { mutateAsync: resumeDocument } = useDocumentResume()
const isListScene = scene === 'list'
@@ -107,6 +110,9 @@ const Operations = ({
else
opApi = syncWebsite
break
case 'summary':
opApi = generateSummary
break
case 'pause':
opApi = pauseDocument
break
@@ -220,6 +226,10 @@ const Operations = ({
<span className={s.actionName}>{t('list.action.sync', { ns: 'datasetDocuments' })}</span>
</div>
)}
<div className={s.actionItem} onClick={() => onOperate('summary')}>
<SearchLinesSparkle className="h-4 w-4 text-text-tertiary" />
<span className={s.actionName}>{t('list.action.summary', { ns: 'datasetDocuments' })}</span>
</div>
<Divider className="my-1" />
</>
)}

View File

@@ -1 +1 @@
export type OperationName = 'delete' | 'archive' | 'enable' | 'disable' | 'sync' | 'un_archive' | 'pause' | 'resume'
export type OperationName = 'delete' | 'archive' | 'enable' | 'disable' | 'sync' | 'un_archive' | 'pause' | 'resume' | 'summary'

View File

@@ -7,6 +7,7 @@ import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Markdown } from '@/app/components/base/markdown'
import SummaryLabel from '@/app/components/datasets/documents/detail/completed/common/summary-label'
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 { cn } from '@/utils/classnames'
@@ -25,7 +26,7 @@ const ResultItem = ({
payload,
}: ResultItemProps) => {
const { t } = useTranslation()
const { segment, score, child_chunks, files } = payload
const { segment, score, child_chunks, files, summary } = payload
const data = segment
const { position, word_count, content, sign_content, keywords, document } = data
const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
@@ -98,6 +99,9 @@ const ResultItem = ({
))}
</div>
)}
{summary && (
<SummaryLabel summary={summary} className="mt-2" />
)}
</div>
{/* Foot */}
<ResultItemFooter docType={fileType} docTitle={document.name} showDetailModal={showDetailModal} />

View File

@@ -2,7 +2,7 @@
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Member } from '@/models/common'
import type { IconInfo } from '@/models/datasets'
import type { IconInfo, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import type { AppIconType, RetrievalConfig } from '@/types/app'
import { RiAlertFill } from '@remixicon/react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@ -33,6 +33,7 @@ import RetrievalSettings from '../../external-knowledge-base/create/RetrievalSet
import ChunkStructure from '../chunk-structure'
import IndexMethod from '../index-method'
import PermissionSelector from '../permission-selector'
import SummaryIndexSetting from '../summary-index-setting'
import { checkShowMultiModalTip } from '../utils'
const rowClass = 'flex gap-x-1'
@@ -76,6 +77,12 @@ const Form = () => {
model: '',
},
)
const [summaryIndexSetting, setSummaryIndexSetting] = useState(currentDataset?.summary_index_setting)
const summaryIndexSettingRef = useRef(currentDataset?.summary_index_setting)
const handleSummaryIndexSettingChange = useCallback((payload: SummaryIndexSettingType) => {
setSummaryIndexSetting({ ...summaryIndexSettingRef.current, ...payload })
summaryIndexSettingRef.current = { ...summaryIndexSettingRef.current, ...payload }
}, [])
const { data: rerankModelList } = useModelList(ModelTypeEnum.rerank)
const { data: embeddingModelList } = useModelList(ModelTypeEnum.textEmbedding)
const { data: membersData } = useMembers()
@@ -167,6 +174,7 @@ const Form = () => {
},
}),
keyword_number: keywordNumber,
summary_index_setting: summaryIndexSetting,
},
} as any
if (permission === DatasetPermission.partialMembers) {
@@ -348,6 +356,21 @@ const Form = () => {
</div>
</div>
)}
{
indexMethod === IndexingType.QUALIFIED && (
<>
<Divider
type="horizontal"
className="my-1 h-px bg-divider-subtle"
/>
<SummaryIndexSetting
entry="dataset-settings"
summaryIndexSetting={summaryIndexSetting}
onSummaryIndexSettingChange={handleSummaryIndexSettingChange}
/>
</>
)
}
{/* Retrieval Method Config */}
{currentDataset?.provider === 'external'
? (

View File

@@ -0,0 +1,228 @@
import type { ChangeEvent } from 'react'
import type { DefaultModel } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import {
memo,
useCallback,
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import Switch from '@/app/components/base/switch'
import Textarea from '@/app/components/base/textarea'
import Tooltip from '@/app/components/base/tooltip'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
type SummaryIndexSettingProps = {
entry?: 'knowledge-base' | 'dataset-settings' | 'create-document'
summaryIndexSetting?: SummaryIndexSettingType
onSummaryIndexSettingChange?: (payload: SummaryIndexSettingType) => void
readonly?: boolean
}
const SummaryIndexSetting = ({
entry = 'knowledge-base',
summaryIndexSetting,
onSummaryIndexSettingChange,
readonly = false,
}: SummaryIndexSettingProps) => {
const { t } = useTranslation()
const {
data: textGenerationModelList,
} = useModelList(ModelTypeEnum.textGeneration)
const summaryIndexModelConfig = useMemo(() => {
if (!summaryIndexSetting?.model_name || !summaryIndexSetting?.model_provider_name)
return undefined
return {
providerName: summaryIndexSetting?.model_provider_name,
modelName: summaryIndexSetting?.model_name,
}
}, [summaryIndexSetting?.model_name, summaryIndexSetting?.model_provider_name])
const handleSummaryIndexEnableChange = useCallback((value: boolean) => {
onSummaryIndexSettingChange?.({
enable: value,
})
}, [onSummaryIndexSettingChange])
const handleSummaryIndexModelChange = useCallback((model: DefaultModel) => {
onSummaryIndexSettingChange?.({
model_provider_name: model.provider,
model_name: model.model,
})
}, [onSummaryIndexSettingChange])
const handleSummaryIndexPromptChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
onSummaryIndexSettingChange?.({
summary_prompt: e.target.value,
})
}, [onSummaryIndexSettingChange])
if (entry === 'knowledge-base') {
return (
<div>
<div className="flex h-6 items-center justify-between">
<div className="system-sm-semibold-uppercase flex items-center text-text-secondary">
{t('form.summaryAutoGen', { ns: 'datasetSettings' })}
<Tooltip
triggerClassName="ml-1 h-4 w-4 shrink-0"
popupContent={t('form.summaryAutoGenTip', { ns: 'datasetSettings' })}
>
</Tooltip>
</div>
<Switch
defaultValue={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>
</div>
{
summaryIndexSetting?.enable && (
<div>
<div className="system-xs-medium-uppercase mb-1.5 mt-2 flex h-6 items-center text-text-tertiary">
{t('form.summaryModel', { ns: 'datasetSettings' })}
</div>
<ModelSelector
defaultModel={summaryIndexModelConfig && { provider: summaryIndexModelConfig.providerName, model: summaryIndexModelConfig.modelName }}
modelList={textGenerationModelList}
onSelect={handleSummaryIndexModelChange}
readonly={readonly}
showDeprecatedWarnIcon
/>
<div className="system-xs-medium-uppercase mt-3 flex h-6 items-center text-text-tertiary">
{t('form.summaryInstructions', { ns: 'datasetSettings' })}
</div>
<Textarea
value={summaryIndexSetting?.summary_prompt ?? ''}
onChange={handleSummaryIndexPromptChange}
disabled={readonly}
placeholder={t('form.summaryInstructionsPlaceholder', { ns: 'datasetSettings' })}
/>
</div>
)
}
</div>
)
}
if (entry === 'dataset-settings') {
return (
<div className="space-y-4">
<div className="flex gap-x-1">
<div className="flex h-7 w-[180px] shrink-0 items-center pt-1">
<div className="system-sm-semibold text-text-secondary">
{t('form.summaryAutoGen', { ns: 'datasetSettings' })}
</div>
</div>
<div className="py-1.5">
<div className="system-sm-semibold flex items-center text-text-secondary">
<Switch
className="mr-2"
defaultValue={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>
{
summaryIndexSetting?.enable ? t('list.status.enabled', { ns: 'datasetDocuments' }) : t('list.status.disabled', { ns: 'datasetDocuments' })
}
</div>
<div className="system-sm-regular mt-2 text-text-tertiary">
{
summaryIndexSetting?.enable && t('form.summaryAutoGenTip', { ns: 'datasetSettings' })
}
{
!summaryIndexSetting?.enable && t('form.summaryAutoGenEnableTip', { ns: 'datasetSettings' })
}
</div>
</div>
</div>
{
summaryIndexSetting?.enable && (
<>
<div className="flex gap-x-1">
<div className="flex h-7 w-[180px] shrink-0 items-center pt-1">
<div className="system-sm-medium text-text-tertiary">
{t('form.summaryModel', { ns: 'datasetSettings' })}
</div>
</div>
<div className="grow">
<ModelSelector
defaultModel={summaryIndexModelConfig && { provider: summaryIndexModelConfig.providerName, model: summaryIndexModelConfig.modelName }}
modelList={textGenerationModelList}
onSelect={handleSummaryIndexModelChange}
readonly={readonly}
showDeprecatedWarnIcon
triggerClassName="h-8"
/>
</div>
</div>
<div className="flex">
<div className="flex h-7 w-[180px] shrink-0 items-center pt-1">
<div className="system-sm-medium text-text-tertiary">
{t('form.summaryInstructions', { ns: 'datasetSettings' })}
</div>
</div>
<div className="grow">
<Textarea
value={summaryIndexSetting?.summary_prompt ?? ''}
onChange={handleSummaryIndexPromptChange}
disabled={readonly}
placeholder={t('form.summaryInstructionsPlaceholder', { ns: 'datasetSettings' })}
/>
</div>
</div>
</>
)
}
</div>
)
}
return (
<div className="space-y-3">
<div className="flex h-6 items-center">
<Switch
className="mr-2"
defaultValue={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>
<div className="system-sm-semibold text-text-secondary">
{t('form.summaryAutoGen', { ns: 'datasetSettings' })}
</div>
</div>
{
summaryIndexSetting?.enable && (
<>
<div>
<div className="system-sm-medium mb-1.5 flex h-6 items-center text-text-secondary">
{t('form.summaryModel', { ns: 'datasetSettings' })}
</div>
<ModelSelector
defaultModel={summaryIndexModelConfig && { provider: summaryIndexModelConfig.providerName, model: summaryIndexModelConfig.modelName }}
modelList={textGenerationModelList}
onSelect={handleSummaryIndexModelChange}
readonly={readonly}
showDeprecatedWarnIcon
triggerClassName="h-8"
/>
</div>
<div>
<div className="system-sm-medium mb-1.5 flex h-6 items-center text-text-secondary">
{t('form.summaryInstructions', { ns: 'datasetSettings' })}
</div>
<Textarea
value={summaryIndexSetting?.summary_prompt ?? ''}
onChange={handleSummaryIndexPromptChange}
disabled={readonly}
placeholder={t('form.summaryInstructionsPlaceholder', { ns: 'datasetSettings' })}
/>
</div>
</>
)
}
</div>
)
}
export default memo(SummaryIndexSetting)

View File

@@ -1,6 +1,7 @@
import type {
KnowledgeBaseNodeType,
RerankingModel,
SummaryIndexSetting,
} from '../types'
import type { ValueSelector } from '@/app/components/workflow/types'
import { produce } from 'immer'
@@ -246,6 +247,16 @@ export const useConfig = (id: string) => {
})
}, [handleNodeDataUpdate])
const handleSummaryIndexSettingChange = useCallback((summaryIndexSetting: SummaryIndexSetting) => {
const nodeData = getNodeData()
handleNodeDataUpdate({
summary_index_setting: {
...nodeData?.data.summary_index_setting,
...summaryIndexSetting,
},
})
}, [handleNodeDataUpdate, getNodeData])
return {
handleChunkStructureChange,
handleIndexMethodChange,
@@ -260,5 +271,6 @@ export const useConfig = (id: string) => {
handleScoreThresholdChange,
handleScoreThresholdEnabledChange,
handleInputVariableChange,
handleSummaryIndexSettingChange,
}
}

View File

@@ -7,6 +7,7 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting'
import { checkShowMultiModalTip } from '@/app/components/datasets/settings/utils'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
@@ -51,6 +52,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
handleScoreThresholdChange,
handleScoreThresholdEnabledChange,
handleInputVariableChange,
handleSummaryIndexSettingChange,
} = useConfig(id)
const filterVar = useCallback((variable: Var) => {
@@ -167,6 +169,20 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
<div className="pt-1">
<Split className="h-[1px]" />
</div>
{
data.indexing_technique === IndexMethodEnum.QUALIFIED && (
<>
<SummaryIndexSetting
summaryIndexSetting={data.summary_index_setting}
onSummaryIndexSettingChange={handleSummaryIndexSettingChange}
readonly={nodesReadOnly}
/>
<div className="pt-1">
<Split className="h-[1px]" />
</div>
</>
)
}
<RetrievalSetting
indexMethod={data.indexing_technique}
searchMethod={data.retrieval_model.search_method}

View File

@@ -42,6 +42,12 @@ export type RetrievalSetting = {
score_threshold: number
reranking_mode?: RerankingModeEnum
}
export type SummaryIndexSetting = {
enable?: boolean
model_name?: string
model_provider_name?: string
summary_prompt?: string
}
export type KnowledgeBaseNodeType = CommonNodeType & {
index_chunk_variable_selector: string[]
chunk_structure?: ChunkStructureEnum
@@ -52,4 +58,5 @@ export type KnowledgeBaseNodeType = CommonNodeType & {
retrieval_model: RetrievalSetting
_embeddingModelList?: Model[]
_rerankModelList?: Model[]
summary_index_setting?: SummaryIndexSetting
}

View File

@@ -30,6 +30,7 @@
"list.action.pause": "Pause",
"list.action.resume": "Resume",
"list.action.settings": "Chunking Settings",
"list.action.summary": "Generate summary",
"list.action.sync": "Sync",
"list.action.unarchive": "Unarchive",
"list.action.uploadFile": "Upload new file",
@@ -74,6 +75,9 @@
"list.status.indexing": "Indexing",
"list.status.paused": "Paused",
"list.status.queuing": "Queuing",
"list.summary.generating": "Generating...",
"list.summary.generatingSummary": "Generating summary",
"list.summary.ready": "Summary ready",
"list.table.header.action": "ACTION",
"list.table.header.chunkingMode": "CHUNKING MODE",
"list.table.header.fileName": "NAME",
@@ -328,5 +332,7 @@
"segment.searchResults_one": "RESULT",
"segment.searchResults_other": "RESULTS",
"segment.searchResults_zero": "RESULT",
"segment.summary": "SUMMARY",
"segment.summaryPlaceholder": "Write a brief summary for better retrieval…",
"segment.vectorHash": "Vector hash: "
}

View File

@@ -39,6 +39,12 @@
"form.retrievalSettings": "Retrieval Settings",
"form.save": "Save",
"form.searchModel": "Search model",
"form.summaryAutoGen": "Summary Auto-Gen",
"form.summaryAutoGenEnableTip": "Once enabled, summaries will be generated automatically for newly added documents. Existing documents can still be summarized manually.",
"form.summaryAutoGenTip": "Summaries are automatically generated for newly added documents. Existing documents can still be summarized manually.",
"form.summaryInstructions": "Instructions",
"form.summaryInstructionsPlaceholder": "Describe the rules or style for auto-generated summaries…",
"form.summaryModel": "Summary Model",
"form.upgradeHighQualityTip": "Once upgrading to High Quality mode, reverting to Economical mode is not available",
"title": "Knowledge settings"
}

View File

@@ -30,6 +30,7 @@
"list.action.pause": "暂停",
"list.action.resume": "恢复",
"list.action.settings": "分段设置",
"list.action.summary": "生成摘要",
"list.action.sync": "同步",
"list.action.unarchive": "撤销归档",
"list.action.uploadFile": "上传新文件",
@@ -74,6 +75,9 @@
"list.status.indexing": "索引中",
"list.status.paused": "已暂停",
"list.status.queuing": "排队中",
"list.summary.generating": "生成中...",
"list.summary.generatingSummary": "生成摘要中",
"list.summary.ready": "摘要已生成",
"list.table.header.action": "操作",
"list.table.header.chunkingMode": "分段模式",
"list.table.header.fileName": "名称",
@@ -328,5 +332,7 @@
"segment.searchResults_one": "搜索结果",
"segment.searchResults_other": "搜索结果",
"segment.searchResults_zero": "搜索结果",
"segment.summary": "摘要",
"segment.summaryPlaceholder": "写一个简短的摘要,以便更好地检索…",
"segment.vectorHash": "向量哈希:"
}

View File

@@ -39,6 +39,12 @@
"form.retrievalSettings": "检索设置",
"form.save": "保存",
"form.searchModel": "搜索模型",
"form.summaryAutoGen": "摘要自动生成",
"form.summaryAutoGenEnableTip": "启用后,将自动为新添加的文档生成摘要。已有的文档仍可以手动摘要。",
"form.summaryAutoGenTip": "将自动为新添加的文档生成摘要。已有的文档仍可以手动摘要。",
"form.summaryInstructions": "指令",
"form.summaryInstructionsPlaceholder": "描述自动生成摘要的规则或风格…",
"form.summaryModel": "摘要模型",
"form.upgradeHighQualityTip": "一旦升级为高质量模式,将无法切换回经济模式。",
"title": "知识库设置"
}

View File

@@ -42,6 +42,13 @@ export type IconInfo = {
icon_url?: string
}
export type SummaryIndexSetting = {
enable?: boolean
model_name?: string
model_provider_name?: string
summary_prompt?: string
}
export type DataSet = {
id: string
name: string
@@ -88,6 +95,7 @@ export type DataSet = {
runtime_mode: 'rag_pipeline' | 'general'
enable_api: boolean // Indicates if the service API is enabled
is_multimodal: boolean // Indicates if the dataset supports multimodal
summary_index_setting?: SummaryIndexSetting
}
export type ExternalAPIItem = {
@@ -262,6 +270,7 @@ export type ProcessRuleResponse = {
mode: ProcessMode
rules: Rules
limits: Limits
summary_index_setting?: SummaryIndexSetting
}
export type Rules = {
@@ -392,6 +401,7 @@ export type InitialDocumentDetail = {
total_segments?: number
doc_form: ChunkingMode
doc_language: string
summary_index_status?: string
}
export type SimpleDocumentDetail = InitialDocumentDetail & {
@@ -425,6 +435,7 @@ export type DocumentReq = {
doc_form: ChunkingMode
doc_language: string
process_rule: ProcessRule
summary_index_setting?: SummaryIndexSetting
}
export type CreateDocumentReq = DocumentReq & {
@@ -467,6 +478,7 @@ export type NotionPage = {
export type ProcessRule = {
mode: ProcessMode
rules: Rules
summary_index_setting?: SummaryIndexSetting
}
export type createDocumentResponse = {
@@ -575,6 +587,7 @@ export type SegmentDetailModel = {
error: string | null
stopped_at: number
answer?: string
summary?: string
child_chunks?: ChildChunkDetail[]
updated_at: number
attachments: Attachment[]
@@ -618,6 +631,7 @@ export type HitTesting = {
tsne_position: TsnePosition
child_chunks: HitTestingChildChunk[] | null
files: Attachment[]
summary?: string
}
export type ExternalKnowledgeBaseHitTesting = {
@@ -697,6 +711,7 @@ export type RelatedAppResponse = {
export type SegmentUpdater = {
content: string
answer?: string
summary?: string
keywords?: string[]
regenerate_child_chunks?: boolean
attachment_ids?: string[]
@@ -778,6 +793,7 @@ export enum DocumentActionType {
archive = 'archive',
unArchive = 'un_archive',
delete = 'delete',
summary = 'summary',
}
export type UpdateDocumentBatchParams = {

View File

@@ -107,6 +107,18 @@ export const useSyncDocument = () => {
})
}
export const useDocumentSummary = () => {
return useMutation({
mutationFn: ({ datasetId, documentIds, documentId }: UpdateDocumentBatchParams) => {
return post<CommonResponse>(`/datasets/${datasetId}/documents/generate-summary`, {
body: {
document_list: documentId ? [documentId] : documentIds!,
},
})
},
})
}
export const useSyncWebsite = () => {
return useMutation({
mutationFn: ({ datasetId, documentId }: UpdateDocumentBatchParams) => {