Merge branch 'main' into feat/hitl-frontend

This commit is contained in:
twwu 2026-01-28 18:29:13 +08:00
commit bf161d01a8
87 changed files with 1075 additions and 102 deletions

View File

@ -22,7 +22,7 @@ from core.plugin.impl.plugin import PluginInstaller
from core.rag.datasource.vdb.vector_factory import Vector
from core.rag.datasource.vdb.vector_type import VectorType
from core.rag.index_processor.constant.built_in_field import BuiltInField
from core.rag.models.document import Document
from core.rag.models.document import ChildDocument, Document
from core.tools.utils.system_oauth_encryption import encrypt_system_oauth_params
from events.app_event import app_was_created
from extensions.ext_database import db
@ -418,6 +418,22 @@ def migrate_knowledge_vector_database():
"dataset_id": segment.dataset_id,
},
)
if dataset_document.doc_form == "hierarchical_model":
child_chunks = segment.get_child_chunks()
if child_chunks:
child_documents = []
for child_chunk in child_chunks:
child_document = ChildDocument(
page_content=child_chunk.content,
metadata={
"doc_id": child_chunk.index_node_id,
"doc_hash": child_chunk.index_node_hash,
"document_id": segment.document_id,
"dataset_id": segment.dataset_id,
},
)
child_documents.append(child_document)
document.children = child_documents
documents.append(document)
segments_count = segments_count + 1
@ -431,7 +447,13 @@ def migrate_knowledge_vector_database():
fg="green",
)
)
all_child_documents = []
for doc in documents:
if doc.children:
all_child_documents.extend(doc.children)
vector.create(documents)
if all_child_documents:
vector.create(all_child_documents)
click.echo(click.style(f"Created vector index for dataset {dataset.id}.", fg="green"))
except Exception as e:
click.echo(click.style(f"Failed to created vector index for dataset {dataset.id}.", fg="red"))

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,9 @@ type GeneralChunkingOptionsProps = {
onReset: () => void
// Locale
locale: string
showSummaryIndexSetting?: boolean
summaryIndexSetting?: SummaryIndexSettingType
onSummaryIndexSettingChange?: (payload: SummaryIndexSettingType) => void
}
export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
@ -74,6 +78,9 @@ export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
onPreview,
onReset,
locale,
showSummaryIndexSetting,
summaryIndexSetting,
onSummaryIndexSettingChange,
}) => {
const { t } = useTranslation()
@ -146,6 +153,17 @@ export const GeneralChunkingOptions: FC<GeneralChunkingOptionsProps> = ({
</label>
</div>
))}
{
showSummaryIndexSetting && (
<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
@ -46,11 +49,13 @@ type ParentChildOptionsProps = {
onRuleToggle: (id: string) => void
onPreview: () => void
onReset: () => void
showSummaryIndexSetting?: boolean
}
export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
parentChildConfig,
rules,
summaryIndexSetting,
currentDocForm: _currentDocForm,
isActive,
isInUpload,
@ -62,8 +67,10 @@ export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
onChildDelimiterChange,
onChildMaxLengthChange,
onRuleToggle,
onSummaryIndexSettingChange,
onPreview,
onReset,
showSummaryIndexSetting,
}) => {
const { t } = useTranslation()
@ -183,6 +190,17 @@ export const ParentChildOptions: FC<ParentChildOptionsProps> = ({
</label>
</div>
))}
{
showSummaryIndexSetting && (
<div className="mt-3">
<SummaryIndexSetting
entry="create-document"
summaryIndexSetting={summaryIndexSetting}
onSummaryIndexSettingChange={onSummaryIndexSettingChange}
/>
</div>
)
}
</div>
</div>
</div>

View File

@ -14,6 +14,7 @@ import { ChunkingMode } from '@/models/datasets'
import { cn } from '@/utils/classnames'
import { ChunkContainer, QAPreview } from '../../../chunk'
import PreviewDocumentPicker from '../../../common/document-picker/preview-document-picker'
import SummaryLabel from '../../../documents/detail/completed/common/summary-label'
import { PreviewSlice } from '../../../formatted-text/flavours/preview-slice'
import { FormattedText } from '../../../formatted-text/formatted'
import PreviewContainer from '../../../preview/container'
@ -99,6 +100,7 @@ export const PreviewPanel: FC<PreviewPanelProps> = ({
characterCount={item.content.length}
>
{item.content}
{item.summary && <SummaryLabel summary={item.summary} />}
</ChunkContainer>
))
)}
@ -131,6 +133,7 @@ export const PreviewPanel: FC<PreviewPanelProps> = ({
)
})}
</FormattedText>
{item.summary && <SummaryLabel summary={item.summary} />}
</ChunkContainer>
)
})

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,5 +1,5 @@
import type { ParentMode, PreProcessingRule, ProcessRule, Rules } from '@/models/datasets'
import { useCallback, useState } from 'react'
import type { ParentMode, PreProcessingRule, ProcessRule, Rules, SummaryIndexSetting as SummaryIndexSettingType } from '@/models/datasets'
import { useCallback, useRef, useState } from 'react'
import { ChunkingMode, ProcessMode } from '@/models/datasets'
import escape from './escape'
import unescape from './unescape'
@ -39,10 +39,11 @@ export const defaultParentChildConfig: ParentChildConfig = {
export type UseSegmentationStateOptions = {
initialSegmentationType?: ProcessMode
initialSummaryIndexSetting?: SummaryIndexSettingType
}
export const useSegmentationState = (options: UseSegmentationStateOptions = {}) => {
const { initialSegmentationType } = options
const { initialSegmentationType, initialSummaryIndexSetting } = options
// Segmentation type (general or parent-child)
const [segmentationType, setSegmentationType] = useState<ProcessMode>(
@ -58,6 +59,15 @@ export const useSegmentationState = (options: UseSegmentationStateOptions = {})
// Pre-processing rules
const [rules, setRules] = useState<PreProcessingRule[]>([])
const [defaultConfig, setDefaultConfig] = useState<Rules>()
const [summaryIndexSetting, setSummaryIndexSetting] = useState<SummaryIndexSettingType | undefined>(initialSummaryIndexSetting)
const summaryIndexSettingRef = useRef<SummaryIndexSettingType | undefined>(initialSummaryIndexSetting)
const handleSummaryIndexSettingChange = useCallback((payload: SummaryIndexSettingType) => {
setSummaryIndexSetting((prev) => {
const newSetting = { ...prev, ...payload }
summaryIndexSettingRef.current = newSetting
return newSetting
})
}, [])
// Parent-child config
const [parentChildConfig, setParentChildConfig] = useState<ParentChildConfig>(defaultParentChildConfig)
@ -134,6 +144,7 @@ export const useSegmentationState = (options: UseSegmentationStateOptions = {})
},
},
mode: 'hierarchical',
summary_index_setting: summaryIndexSettingRef.current,
} as ProcessRule
}
@ -147,6 +158,7 @@ export const useSegmentationState = (options: UseSegmentationStateOptions = {})
},
},
mode: segmentationType,
summary_index_setting: summaryIndexSettingRef.current,
} as ProcessRule
}, [rules, parentChildConfig, segmentIdentifier, maxChunkLength, overlap, segmentationType])
@ -204,6 +216,8 @@ export const useSegmentationState = (options: UseSegmentationStateOptions = {})
defaultConfig,
setDefaultConfig,
toggleRule,
summaryIndexSetting,
handleSummaryIndexSettingChange,
// Parent-child config
parentChildConfig,

View File

@ -65,7 +65,9 @@ const StepTwo: FC<StepTwoProps> = ({
// Custom hooks
const segmentation = useSegmentationState({
initialSegmentationType: currentDataset?.doc_form === ChunkingMode.parentChild ? ProcessMode.parentChild : ProcessMode.general,
initialSummaryIndexSetting: currentDataset?.summary_index_setting,
})
const showSummaryIndexSetting = !currentDataset
const indexing = useIndexingConfig({
initialIndexType: propsIndexingType,
initialEmbeddingModel: currentDataset?.embedding_model ? { provider: currentDataset.embedding_model_provider, model: currentDataset.embedding_model } : undefined,
@ -156,7 +158,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(), segmentation.summaryIndexSetting)
if (!params)
return
await creation.executeCreation(params, indexing.indexType, indexing.retrievalConfig)
@ -217,6 +219,9 @@ const StepTwo: FC<StepTwoProps> = ({
onPreview={updatePreview}
onReset={segmentation.resetToDefaults}
locale={locale}
showSummaryIndexSetting={showSummaryIndexSetting}
summaryIndexSetting={segmentation.summaryIndexSetting}
onSummaryIndexSettingChange={segmentation.handleSummaryIndexSettingChange}
/>
)}
{showParentChildOption && (
@ -236,6 +241,9 @@ const StepTwo: FC<StepTwoProps> = ({
onRuleToggle={segmentation.toggleRule}
onPreview={updatePreview}
onReset={segmentation.resetToDefaults}
showSummaryIndexSetting={showSummaryIndexSetting}
summaryIndexSetting={segmentation.summaryIndexSetting}
onSummaryIndexSettingChange={segmentation.handleSummaryIndexSettingChange}
/>
)}
<Divider className="my-5" />

View File

@ -30,12 +30,13 @@ 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, useDocumentDownloadZip, useDocumentEnable } from '@/service/knowledge/use-document'
import { useDocumentArchive, useDocumentBatchRetryIndex, useDocumentDelete, useDocumentDisable, useDocumentDownloadZip, useDocumentEnable, useDocumentSummary } from '@/service/knowledge/use-document'
import { asyncRunSafe } from '@/utils'
import { cn } from '@/utils/classnames'
import { downloadBlob } from '@/utils/download'
import { formatNumber } from '@/utils/format'
import BatchAction from '../detail/completed/common/batch-action'
import SummaryStatus from '../detail/completed/common/summary-status'
import StatusItem from '../status-item'
import s from '../style.module.css'
import Operations from './operations'
@ -219,6 +220,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()
@ -232,6 +234,9 @@ const DocumentList: FC<IDocumentListProps> = ({
case DocumentActionType.archive:
opApi = archiveDocument
break
case DocumentActionType.summary:
opApi = generateSummary
break
case DocumentActionType.enable:
opApi = enableDocument
break
@ -444,6 +449,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' })}
@ -496,6 +508,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)}
onBatchDownload={downloadableSelectedIds.length > 0 ? handleBatchDownload : undefined}

View File

@ -15,6 +15,7 @@ vi.mock('@/service/knowledge/use-document', () => ({
useSyncWebsite: () => ({ mutateAsync: vi.fn().mockResolvedValue({}) }),
useDocumentPause: () => ({ mutateAsync: vi.fn().mockResolvedValue({}) }),
useDocumentResume: () => ({ mutateAsync: vi.fn().mockResolvedValue({}) }),
useDocumentSummary: () => ({ mutateAsync: vi.fn().mockResolvedValue({}) }),
}))
// Mock utils

View File

@ -21,6 +21,7 @@ import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
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 CustomPopover from '@/app/components/base/popover'
import Switch from '@/app/components/base/switch'
import { ToastContext } from '@/app/components/base/toast'
@ -34,6 +35,7 @@ import {
useDocumentEnable,
useDocumentPause,
useDocumentResume,
useDocumentSummary,
useDocumentUnArchive,
useSyncDocument,
useSyncWebsite,
@ -87,6 +89,7 @@ const Operations = ({
const { mutateAsync: downloadDocument, isPending: isDownloading } = useDocumentDownload()
const { mutateAsync: syncDocument } = useSyncDocument()
const { mutateAsync: syncWebsite } = useSyncWebsite()
const { mutateAsync: generateSummary } = useDocumentSummary()
const { mutateAsync: pauseDocument } = useDocumentPause()
const { mutateAsync: resumeDocument } = useDocumentResume()
const isListScene = scene === 'list'
@ -112,6 +115,9 @@ const Operations = ({
else
opApi = syncWebsite
break
case 'summary':
opApi = generateSummary
break
case 'pause':
opApi = pauseDocument
break
@ -257,6 +263,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

@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge'
import Button from '@/app/components/base/button'
import { SkeletonContainer, SkeletonPoint, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
import SummaryLabel from '@/app/components/datasets/documents/detail/completed/common/summary-label'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { ChunkingMode } from '@/models/datasets'
import { DatasourceType } from '@/models/pipeline'
@ -181,6 +182,7 @@ const ChunkPreview = ({
characterCount={item.content.length}
>
{item.content}
{item.summary && <SummaryLabel summary={item.summary} />}
</ChunkContainer>
))
)}
@ -207,6 +209,7 @@ const ChunkPreview = ({
/>
)
})}
{item.summary && <SummaryLabel summary={item.summary} />}
</FormattedText>
</ChunkContainer>
)

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'
@ -16,6 +17,7 @@ type IBatchActionProps = {
onBatchDisable: () => void
onBatchDownload?: () => void
onBatchDelete: () => Promise<void>
onBatchSummary?: () => void
onArchive?: () => void
onEditMetadata?: () => void
onBatchReIndex?: () => void
@ -27,6 +29,7 @@ const BatchAction: FC<IBatchActionProps> = ({
selectedIds,
onBatchEnable,
onBatchDisable,
onBatchSummary,
onBatchDownload,
onArchive,
onBatchDelete,
@ -84,7 +87,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,37 @@
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 === 'SUMMARIZING') {
return t('list.summary.generatingSummary', { ns: 'datasetDocuments' })
}
return ''
}, [status, t])
return (
<Tooltip
popupContent={tip}
>
{
status === 'SUMMARIZING' && (
<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

@ -22,6 +22,7 @@ type DrawerGroupProps = {
answer: string,
keywords: string[],
attachments: FileEntity[],
summary?: string,
needRegenerate?: boolean,
) => Promise<void>
isRegenerationModalOpen: boolean

View File

@ -614,7 +614,7 @@ describe('useSegmentListData', () => {
})
await act(async () => {
await result.current.handleUpdateSegment('seg-1', 'content', '', [], [], true)
await result.current.handleUpdateSegment('seg-1', 'content', '', [], [], 'summary', true)
})
expect(onCloseSegmentDetail).not.toHaveBeenCalled()

View File

@ -53,6 +53,7 @@ export type UseSegmentListDataReturn = {
answer: string,
keywords: string[],
attachments: FileEntity[],
summary?: string,
needRegenerate?: boolean,
) => Promise<void>
resetList: () => void
@ -248,6 +249,7 @@ export const useSegmentListData = (options: UseSegmentListDataOptions): UseSegme
answer: string,
keywords: string[],
attachments: FileEntity[],
summary?: string,
needRegenerate = false,
) => {
const params: SegmentUpdater = { content: '', attachment_ids: [] }
@ -285,6 +287,8 @@ export const useSegmentListData = (options: UseSegmentListDataOptions): UseSegme
params.attachment_ids = attachments.map(item => item.uploadedId!)
}
params.summary = summary ?? ''
if (needRegenerate)
params.regenerate_child_chunks = needRegenerate
@ -302,6 +306,7 @@ export const useSegmentListData = (options: UseSegmentListDataOptions): UseSegme
sign_content: res.data.sign_content,
keywords: res.data.keywords,
attachments: res.data.attachments,
summary: res.data.summary,
word_count: res.data.word_count,
hit_count: res.data.hit_count,
enabled: res.data.enabled,

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

@ -356,6 +356,8 @@ describe('SegmentDetail', () => {
expect.any(String),
expect.any(Array),
expect.any(Array),
expect.any(String),
expect.any(Boolean),
)
})
@ -545,6 +547,8 @@ describe('SegmentDetail', () => {
expect.any(String),
expect.any(Array),
expect.arrayContaining([expect.objectContaining({ id: 'new-attachment' })]),
expect.any(String),
expect.any(Boolean),
)
})
@ -585,6 +589,7 @@ describe('SegmentDetail', () => {
expect.any(String),
expect.any(Array),
expect.any(Array),
expect.any(String),
true,
)
})

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

@ -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

@ -12,6 +12,7 @@ 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 SummaryText from '../../documents/detail/completed/common/summary-text'
import ChildChunksItem from './child-chunks-item'
import Mask from './mask'
import Score from './score'
@ -28,7 +29,7 @@ const ChunkDetailModal = ({
onHide,
}: ChunkDetailModalProps) => {
const { t } = useTranslation()
const { segment, score, child_chunks, files } = payload
const { segment, score, child_chunks, files, summary } = payload
const { position, content, sign_content, keywords, document, answer } = segment
const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
const extension = document.name.split('.').slice(-1)[0] as FileAppearanceTypeEnum
@ -104,11 +105,14 @@ const ChunkDetailModal = ({
{/* Mask */}
<Mask className="absolute inset-x-0 bottom-0" />
</div>
{(showImages || showKeywords) && (
{(showImages || showKeywords || !!summary) && (
<div className="flex flex-col gap-y-3 pt-3">
{showImages && (
<ImageList images={images} size="md" className="py-1" />
)}
{!!summary && (
<SummaryText value={summary} disabled />
)}
{showKeywords && (
<div className="flex flex-col gap-y-1">
<div className="text-xs font-medium uppercase text-text-tertiary">{t(`${i18nPrefix}keyword`, { ns: 'datasetHitTesting' })}</div>

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 handleSummaryIndexSettingChange = useCallback((payload: SummaryIndexSettingType) => {
setSummaryIndexSetting((prev) => {
return { ...prev, ...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,23 @@ const Form = () => {
</div>
</div>
)}
{
indexMethod === IndexingType.QUALIFIED
&& [ChunkingMode.text, ChunkingMode.parentChild].includes(currentDataset?.doc_form as ChunkingMode)
&& (
<>
<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,10 +1,11 @@
import type { QAChunk } from './types'
import type { GeneralChunk, ParentChildChunk, QAChunk } from './types'
import type { ParentMode } from '@/models/datasets'
import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Dot from '@/app/components/datasets/documents/detail/completed/common/dot'
import SegmentIndexTag from '@/app/components/datasets/documents/detail/completed/common/segment-index-tag'
import SummaryLabel from '@/app/components/datasets/documents/detail/completed/common/summary-label'
import { PreviewSlice } from '@/app/components/datasets/formatted-text/flavours/preview-slice'
import { ChunkingMode } from '@/models/datasets'
import { formatNumber } from '@/utils/format'
@ -14,7 +15,7 @@ import { QAItemType } from './types'
type ChunkCardProps = {
chunkType: ChunkingMode
parentMode?: ParentMode
content: string | string[] | QAChunk
content: ParentChildChunk | QAChunk | GeneralChunk
positionId?: string | number
wordCount: number
}
@ -33,7 +34,7 @@ const ChunkCard = (props: ChunkCardProps) => {
const contentElement = useMemo(() => {
if (chunkType === ChunkingMode.parentChild) {
return (content as string[]).map((child, index) => {
return (content as ParentChildChunk).child_contents.map((child, index) => {
const indexForLabel = index + 1
return (
<PreviewSlice
@ -57,7 +58,17 @@ const ChunkCard = (props: ChunkCardProps) => {
)
}
return content as string
return (content as GeneralChunk).content
}, [content, chunkType])
const summaryElement = useMemo(() => {
if (chunkType === ChunkingMode.parentChild) {
return (content as ParentChildChunk).parent_summary
}
if (chunkType === ChunkingMode.text) {
return (content as GeneralChunk).summary
}
return null
}, [content, chunkType])
return (
@ -73,6 +84,7 @@ const ChunkCard = (props: ChunkCardProps) => {
</div>
)}
<div className="body-md-regular text-text-secondary">{contentElement}</div>
{summaryElement && <SummaryLabel summary={summaryElement} />}
</div>
)
}

View File

@ -10,13 +10,13 @@ import { QAItemType } from './types'
// Test Data Factories
// =============================================================================
const createGeneralChunks = (overrides: string[] = []): GeneralChunks => {
const createGeneralChunks = (overrides: GeneralChunks = []): GeneralChunks => {
if (overrides.length > 0)
return overrides
return [
'This is the first chunk of text content.',
'This is the second chunk with different content.',
'Third chunk here with more text.',
{ content: 'This is the first chunk of text content.' },
{ content: 'This is the second chunk with different content.' },
{ content: 'Third chunk here with more text.' },
]
}
@ -152,14 +152,14 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="This is plain text content."
content={createGeneralChunks()[0]}
wordCount={27}
positionId={1}
/>,
)
// Assert
expect(screen.getByText('This is plain text content.')).toBeInTheDocument()
expect(screen.getByText('This is the first chunk of text content.')).toBeInTheDocument()
expect(screen.getByText(/Chunk-01/)).toBeInTheDocument()
})
@ -196,7 +196,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="paragraph"
content={childContents}
content={createParentChildChunk({ child_contents: childContents })}
wordCount={50}
positionId={1}
/>,
@ -218,7 +218,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="paragraph"
content={['Child content']}
content={createParentChildChunk({ child_contents: ['Child content'] })}
wordCount={13}
positionId={1}
/>,
@ -234,7 +234,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="full-doc"
content={['Child content']}
content={createParentChildChunk({ child_contents: ['Child content'] })}
wordCount={13}
positionId={1}
/>,
@ -250,7 +250,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Text content"
content={createGeneralChunks()[0]}
wordCount={12}
positionId={5}
/>,
@ -268,7 +268,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Some content"
content={createGeneralChunks()[0]}
wordCount={1234}
positionId={1}
/>,
@ -283,7 +283,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Some content"
content={createGeneralChunks()[0]}
wordCount={100}
positionId={1}
/>,
@ -299,7 +299,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="full-doc"
content={['Child']}
content={createParentChildChunk({ child_contents: ['Child'] })}
wordCount={500}
positionId={1}
/>,
@ -317,7 +317,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Content"
content={createGeneralChunks()[0]}
wordCount={7}
positionId={42}
/>,
@ -332,7 +332,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Content"
content={createGeneralChunks()[0]}
wordCount={7}
positionId="99"
/>,
@ -347,7 +347,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Content"
content={createGeneralChunks()[0]}
wordCount={7}
positionId={3}
/>,
@ -366,7 +366,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="paragraph"
content={['Child']}
content={createParentChildChunk({ child_contents: ['Child'] })}
wordCount={5}
positionId={1}
/>,
@ -380,7 +380,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="full-doc"
content={['Child']}
content={createParentChildChunk({ child_contents: ['Child'] })}
wordCount={5}
positionId={1}
/>,
@ -392,10 +392,13 @@ describe('ChunkCard', () => {
it('should update contentElement memo when content changes', () => {
// Arrange
const initialContent = { content: 'Initial content' }
const updatedContent = { content: 'Updated content' }
const { rerender } = render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Initial content"
content={initialContent}
wordCount={15}
positionId={1}
/>,
@ -408,7 +411,7 @@ describe('ChunkCard', () => {
rerender(
<ChunkCard
chunkType={ChunkingMode.text}
content="Updated content"
content={updatedContent}
wordCount={15}
positionId={1}
/>,
@ -421,10 +424,11 @@ describe('ChunkCard', () => {
it('should update contentElement memo when chunkType changes', () => {
// Arrange
const textContent = { content: 'Text content' }
const { rerender } = render(
<ChunkCard
chunkType={ChunkingMode.text}
content="Text content"
content={textContent}
wordCount={12}
positionId={1}
/>,
@ -458,7 +462,7 @@ describe('ChunkCard', () => {
<ChunkCard
chunkType={ChunkingMode.parentChild}
parentMode="paragraph"
content={[]}
content={createParentChildChunk({ child_contents: [] })}
wordCount={0}
positionId={1}
/>,
@ -490,12 +494,13 @@ describe('ChunkCard', () => {
it('should handle very long content', () => {
// Arrange
const longContent = 'A'.repeat(10000)
const longContentChunk = { content: longContent }
// Act
render(
<ChunkCard
chunkType={ChunkingMode.text}
content={longContent}
content={longContentChunk}
wordCount={10000}
positionId={1}
/>,
@ -510,7 +515,7 @@ describe('ChunkCard', () => {
render(
<ChunkCard
chunkType={ChunkingMode.text}
content=""
content={createGeneralChunks()[0]}
wordCount={0}
positionId={1}
/>,
@ -546,9 +551,9 @@ describe('ChunkCardList', () => {
)
// Assert
expect(screen.getByText(chunks[0])).toBeInTheDocument()
expect(screen.getByText(chunks[1])).toBeInTheDocument()
expect(screen.getByText(chunks[2])).toBeInTheDocument()
expect(screen.getByText(chunks[0].content)).toBeInTheDocument()
expect(screen.getByText(chunks[1].content)).toBeInTheDocument()
expect(screen.getByText(chunks[2].content)).toBeInTheDocument()
})
it('should render parent-child chunks correctly', () => {
@ -594,7 +599,10 @@ describe('ChunkCardList', () => {
describe('Memoization - chunkList', () => {
it('should extract chunks from GeneralChunks for text mode', () => {
// Arrange
const chunks: GeneralChunks = ['Chunk 1', 'Chunk 2']
const chunks: GeneralChunks = [
{ content: 'Chunk 1' },
{ content: 'Chunk 2' },
]
// Act
render(
@ -653,7 +661,7 @@ describe('ChunkCardList', () => {
it('should update chunkList when chunkInfo changes', () => {
// Arrange
const initialChunks = createGeneralChunks(['Initial chunk'])
const initialChunks = createGeneralChunks([{ content: 'Initial chunk' }])
const { rerender } = render(
<ChunkCardList
@ -666,7 +674,7 @@ describe('ChunkCardList', () => {
expect(screen.getByText('Initial chunk')).toBeInTheDocument()
// Act - update chunks
const updatedChunks = createGeneralChunks(['Updated chunk'])
const updatedChunks = createGeneralChunks([{ content: 'Updated chunk' }])
rerender(
<ChunkCardList
chunkType={ChunkingMode.text}
@ -684,7 +692,7 @@ describe('ChunkCardList', () => {
describe('Word Count Calculation', () => {
it('should calculate word count for text chunks using string length', () => {
// Arrange - "Hello" has 5 characters
const chunks = createGeneralChunks(['Hello'])
const chunks = createGeneralChunks([{ content: 'Hello' }])
// Act
render(
@ -747,7 +755,11 @@ describe('ChunkCardList', () => {
describe('Position ID', () => {
it('should assign 1-based position IDs to chunks', () => {
// Arrange
const chunks = createGeneralChunks(['First', 'Second', 'Third'])
const chunks = createGeneralChunks([
{ content: 'First' },
{ content: 'Second' },
{ content: 'Third' },
])
// Act
render(
@ -768,7 +780,7 @@ describe('ChunkCardList', () => {
describe('Custom className', () => {
it('should apply custom className to container', () => {
// Arrange
const chunks = createGeneralChunks(['Test'])
const chunks = createGeneralChunks([{ content: 'Test' }])
// Act
const { container } = render(
@ -785,7 +797,7 @@ describe('ChunkCardList', () => {
it('should merge custom className with default classes', () => {
// Arrange
const chunks = createGeneralChunks(['Test'])
const chunks = createGeneralChunks([{ content: 'Test' }])
// Act
const { container } = render(
@ -805,7 +817,7 @@ describe('ChunkCardList', () => {
it('should render without className prop', () => {
// Arrange
const chunks = createGeneralChunks(['Test'])
const chunks = createGeneralChunks([{ content: 'Test' }])
// Act
const { container } = render(
@ -860,7 +872,7 @@ describe('ChunkCardList', () => {
it('should not use parentMode for text type', () => {
// Arrange
const chunks = createGeneralChunks(['Text'])
const chunks = createGeneralChunks([{ content: 'Text' }])
// Act
render(
@ -937,7 +949,7 @@ describe('ChunkCardList', () => {
it('should handle single item in chunks', () => {
// Arrange
const chunks = createGeneralChunks(['Single chunk'])
const chunks = createGeneralChunks([{ content: 'Single chunk' }])
// Act
render(
@ -954,7 +966,7 @@ describe('ChunkCardList', () => {
it('should handle large number of chunks', () => {
// Arrange
const chunks = Array.from({ length: 100 }, (_, i) => `Chunk number ${i + 1}`)
const chunks = Array.from({ length: 100 }, (_, i) => ({ content: `Chunk number ${i + 1}` }))
// Act
render(
@ -975,8 +987,11 @@ describe('ChunkCardList', () => {
describe('Key Generation', () => {
it('should generate unique keys for chunks', () => {
// Arrange - chunks with same content
const chunks = createGeneralChunks(['Same content', 'Same content', 'Same content'])
const chunks = createGeneralChunks([
{ content: 'Same content' },
{ content: 'Same content' },
{ content: 'Same content' },
])
// Act
const { container } = render(
<ChunkCardList
@ -1006,9 +1021,9 @@ describe('ChunkCardList Integration', () => {
it('should render complete text chunking workflow', () => {
// Arrange
const textChunks = createGeneralChunks([
'First paragraph of the document.',
'Second paragraph with more information.',
'Final paragraph concluding the content.',
{ content: 'First paragraph of the document.' },
{ content: 'Second paragraph with more information.' },
{ content: 'Final paragraph concluding the content.' },
])
// Act
@ -1104,7 +1119,7 @@ describe('ChunkCardList Integration', () => {
describe('Type Switching', () => {
it('should handle switching from text to QA type', () => {
// Arrange
const textChunks = createGeneralChunks(['Text content'])
const textChunks = createGeneralChunks([{ content: 'Text content' }])
const qaChunks = createQAChunks()
const { rerender } = render(
@ -1132,7 +1147,7 @@ describe('ChunkCardList Integration', () => {
it('should handle switching from text to parent-child type', () => {
// Arrange
const textChunks = createGeneralChunks(['Simple text'])
const textChunks = createGeneralChunks([{ content: 'Simple text' }])
const parentChildChunks = createParentChildChunks()
const { rerender } = render(

View File

@ -1,4 +1,4 @@
import type { ChunkInfo, GeneralChunks, ParentChildChunk, ParentChildChunks, QAChunk, QAChunks } from './types'
import type { ChunkInfo, GeneralChunk, GeneralChunks, ParentChildChunk, ParentChildChunks, QAChunk, QAChunks } from './types'
import type { ParentMode } from '@/models/datasets'
import { useMemo } from 'react'
import { ChunkingMode } from '@/models/datasets'
@ -21,13 +21,13 @@ export const ChunkCardList = (props: ChunkCardListProps) => {
if (chunkType === ChunkingMode.parentChild)
return (chunkInfo as ParentChildChunks).parent_child_chunks
return (chunkInfo as QAChunks).qa_chunks
}, [chunkInfo])
}, [chunkInfo, chunkType])
const getWordCount = (seg: string | ParentChildChunk | QAChunk) => {
const getWordCount = (seg: GeneralChunk | ParentChildChunk | QAChunk) => {
if (chunkType === ChunkingMode.parentChild)
return (seg as ParentChildChunk).parent_content.length
return (seg as ParentChildChunk).parent_content?.length
if (chunkType === ChunkingMode.text)
return (seg as string).length
return (seg as GeneralChunk).content.length
return (seg as QAChunk).question.length + (seg as QAChunk).answer.length
}
@ -41,7 +41,7 @@ export const ChunkCardList = (props: ChunkCardListProps) => {
key={`${chunkType}-${index}`}
chunkType={chunkType}
parentMode={parentMode}
content={chunkType === ChunkingMode.parentChild ? (seg as ParentChildChunk).child_contents : (seg as string | QAChunk)}
content={seg}
wordCount={wordCount}
positionId={index + 1}
/>

View File

@ -1,8 +1,12 @@
export type GeneralChunks = string[]
export type GeneralChunk = {
content: string
summary?: string
}
export type GeneralChunks = GeneralChunk[]
export type ParentChildChunk = {
child_contents: string[]
parent_content: string
parent_summary?: string
parent_mode: string
}

View File

@ -1,8 +1,8 @@
import type { GeneralChunks } from '@/app/components/rag-pipeline/components/chunk-card-list/types'
import type { WorkflowRunningData } from '@/app/components/workflow/types'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
import { ChunkingMode } from '@/models/datasets'
import Header from './header'
// Import components after mocks
import TestRunPanel from './index'
@ -830,17 +830,27 @@ describe('formatPreviewChunks', () => {
const outputs = createMockGeneralOutputs(['content1', 'content2', 'content3'])
const result = formatPreviewChunks(outputs)
expect(result).toEqual(['content1', 'content2', 'content3'])
expect(result).toEqual([
{ content: 'content1', summary: undefined },
{ content: 'content2', summary: undefined },
{ content: 'content3', summary: undefined },
])
})
it('should limit to RAG_PIPELINE_PREVIEW_CHUNK_NUM chunks', () => {
const manyChunks = Array.from({ length: 10 }, (_, i) => `chunk${i}`)
const outputs = createMockGeneralOutputs(manyChunks)
const result = formatPreviewChunks(outputs) as string[]
const result = formatPreviewChunks(outputs) as GeneralChunks
// RAG_PIPELINE_PREVIEW_CHUNK_NUM is mocked to 5
expect(result).toHaveLength(5)
expect(result).toEqual(['chunk0', 'chunk1', 'chunk2', 'chunk3', 'chunk4'])
expect(result).toEqual([
{ content: 'chunk0', summary: undefined },
{ content: 'chunk1', summary: undefined },
{ content: 'chunk2', summary: undefined },
{ content: 'chunk3', summary: undefined },
{ content: 'chunk4', summary: undefined },
])
})
it('should handle empty preview array', () => {

View File

@ -590,9 +590,9 @@ describe('formatPreviewChunks', () => {
const result = formatPreviewChunks(outputs) as GeneralChunks
expect(result).toHaveLength(3)
expect(result[0]).toBe('General chunk content 1')
expect(result[1]).toBe('General chunk content 2')
expect(result[2]).toBe('General chunk content 3')
expect((result as GeneralChunks)[0].content).toBe('General chunk content 1')
expect((result as GeneralChunks)[1].content).toBe('General chunk content 2')
expect((result as GeneralChunks)[2].content).toBe('General chunk content 3')
})
it('should limit chunks to RAG_PIPELINE_PREVIEW_CHUNK_NUM', () => {

View File

@ -145,9 +145,9 @@ describe('formatPreviewChunks', () => {
// Assert
expect(result).toEqual([
'First chunk content',
'Second chunk content',
'Third chunk content',
{ content: 'First chunk content', summary: undefined },
{ content: 'Second chunk content', summary: undefined },
{ content: 'Third chunk content', summary: undefined },
])
})
@ -160,8 +160,8 @@ describe('formatPreviewChunks', () => {
// Assert
expect(result).toHaveLength(20)
expect(result[0]).toBe('Chunk content 1')
expect(result[19]).toBe('Chunk content 20')
expect((result as GeneralChunks)[0].content).toBe('Chunk content 1')
expect((result as GeneralChunks)[19].content).toBe('Chunk content 20')
})
it('should handle empty preview array for general chunks', () => {
@ -186,7 +186,10 @@ describe('formatPreviewChunks', () => {
const result = formatPreviewChunks(outputs) as GeneralChunks
// Assert
expect(result).toEqual(['', 'Valid content'])
expect(result).toEqual([
{ content: '', summary: undefined },
{ content: 'Valid content', summary: undefined },
])
})
it('should handle general chunks with special characters', () => {
@ -202,9 +205,9 @@ describe('formatPreviewChunks', () => {
// Assert
expect(result).toEqual([
'<script>alert("xss")</script>',
'中文内容 🎉',
'Line1\nLine2\tTab',
{ content: '<script>alert("xss")</script>', summary: undefined },
{ content: '中文内容 🎉', summary: undefined },
{ content: 'Line1\nLine2\tTab', summary: undefined },
])
})
@ -217,7 +220,7 @@ describe('formatPreviewChunks', () => {
const result = formatPreviewChunks(outputs) as GeneralChunks
// Assert
expect(result[0]).toHaveLength(10000)
expect((result as GeneralChunks)[0].content).toHaveLength(10000)
})
})
@ -501,7 +504,7 @@ describe('formatPreviewChunks', () => {
const result = formatPreviewChunks(outputs) as GeneralChunks
// Assert
expect(result).toEqual(['Test'])
expect(result).toEqual([{ content: 'Test', summary: undefined }])
})
})
})
@ -667,7 +670,10 @@ describe('ResultPreview', () => {
// Assert
const chunkList = screen.getByTestId('chunk-card-list')
const chunkInfo = JSON.parse(chunkList.getAttribute('data-chunk-info') || '[]')
expect(chunkInfo).toEqual(['Chunk 1', 'Chunk 2'])
expect(chunkInfo).toEqual([
{ content: 'Chunk 1' },
{ content: 'Chunk 2' },
])
})
it('should handle parent-child outputs', () => {
@ -792,7 +798,7 @@ describe('ResultPreview', () => {
// Assert
const chunkList = screen.getByTestId('chunk-card-list')
const chunkInfo = JSON.parse(chunkList.getAttribute('data-chunk-info') || '[]')
expect(chunkInfo).toEqual(['Second'])
expect(chunkInfo).toEqual([{ content: 'Second' }])
})
})
@ -820,7 +826,7 @@ describe('ResultPreview', () => {
let chunkList = screen.getByTestId('chunk-card-list')
let chunkInfo = JSON.parse(chunkList.getAttribute('data-chunk-info') || '[]')
expect(chunkInfo).toEqual(['Original'])
expect(chunkInfo).toEqual([{ content: 'Original' }])
// Act - Change outputs
const outputs2 = createGeneralChunkOutputs([{ content: 'Updated' }])
@ -829,7 +835,7 @@ describe('ResultPreview', () => {
// Assert
chunkList = screen.getByTestId('chunk-card-list')
chunkInfo = JSON.parse(chunkList.getAttribute('data-chunk-info') || '[]')
expect(chunkInfo).toEqual(['Updated'])
expect(chunkInfo).toEqual([{ content: 'Updated' }])
})
it('should handle undefined outputs in useMemo', () => {

View File

@ -5,13 +5,17 @@ import { ChunkingMode } from '@/models/datasets'
type GeneralChunkPreview = {
content: string
summary?: string
}
const formatGeneralChunks = (outputs: any) => {
const chunkInfo: GeneralChunks = []
const chunks = outputs.preview as GeneralChunkPreview[]
chunks.slice(0, RAG_PIPELINE_PREVIEW_CHUNK_NUM).forEach((chunk) => {
chunkInfo.push(chunk.content)
chunkInfo.push({
content: chunk.content,
summary: chunk.summary,
})
})
return chunkInfo
@ -20,6 +24,7 @@ const formatGeneralChunks = (outputs: any) => {
type ParentChildChunkPreview = {
content: string
child_chunks: string[]
summary?: string
}
const formatParentChildChunks = (outputs: any, parentMode: ParentMode) => {
@ -32,6 +37,7 @@ const formatParentChildChunks = (outputs: any, parentMode: ParentMode) => {
chunks.slice(0, RAG_PIPELINE_PREVIEW_CHUNK_NUM).forEach((chunk) => {
chunkInfo.parent_child_chunks?.push({
parent_content: chunk.content,
parent_summary: chunk.summary,
child_contents: chunk.child_chunks,
parent_mode: parentMode,
})

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,22 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
<div className="pt-1">
<Split className="h-[1px]" />
</div>
{
data.indexing_technique === IndexMethodEnum.QUALIFIED
&& [ChunkStructureEnum.general, ChunkStructureEnum.parent_child].includes(data.chunk_structure)
&& (
<>
<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

@ -31,6 +31,7 @@
"list.action.pause": "إيقاف مؤقت",
"list.action.resume": "استئناف",
"list.action.settings": "إعدادات التقطيع",
"list.action.summary": "إنشاء ملخص",
"list.action.sync": "مزامنة",
"list.action.unarchive": "إلغاء الأرشفة",
"list.action.uploadFile": "تحميل ملف جديد",
@ -75,6 +76,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": "الاسم",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Pause",
"list.action.resume": "Fortsetzen",
"list.action.settings": "Segment-Einstellungen",
"list.action.summary": "Zusammenfassung generieren",
"list.action.sync": "Synchronisieren",
"list.action.unarchive": "Archivierung aufheben",
"list.action.uploadFile": "Neue Datei hochladen",
@ -75,6 +76,9 @@
"list.status.indexing": "Indizierung",
"list.status.paused": "Pausiert",
"list.status.queuing": "In Warteschlange",
"list.summary.generating": "Wird generiert...",
"list.summary.generatingSummary": "Zusammenfassung wird generiert",
"list.summary.ready": "Zusammenfassung bereit",
"list.table.header.action": "AKTION",
"list.table.header.chunkingMode": "CHUNKING-MODUS",
"list.table.header.fileName": "DATEINAME",
@ -329,5 +333,7 @@
"segment.searchResults_one": "ERGEBNIS",
"segment.searchResults_other": "BEFUND",
"segment.searchResults_zero": "ERGEBNIS",
"segment.summary": "ZUSAMMENFASSUNG",
"segment.summaryPlaceholder": "Schreiben Sie eine kurze Zusammenfassung für bessere Abrufbarkeit…",
"segment.vectorHash": "Vektor-Hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Einstellungen für den Abruf",
"form.save": "Speichern",
"form.searchModel": "Modell suchen",
"form.summaryAutoGen": "Automatische Zusammenfassungserstellung",
"form.summaryAutoGenEnableTip": "Nach der Aktivierung werden Zusammenfassungen automatisch für neu hinzugefügte Dokumente generiert. Vorhandene Dokumente können weiterhin manuell zusammengefasst werden.",
"form.summaryAutoGenTip": "Zusammenfassungen werden automatisch für neu hinzugefügte Dokumente generiert. Vorhandene Dokumente können weiterhin manuell zusammengefasst werden.",
"form.summaryInstructions": "Anweisungen",
"form.summaryInstructionsPlaceholder": "Beschreiben Sie die Regeln oder den Stil für automatisch generierte Zusammenfassungen…",
"form.summaryModel": "Zusammenfassungsmodell",
"form.upgradeHighQualityTip": "Nach dem Upgrade auf den Modus \"Hohe Qualität\" ist das Zurücksetzen auf den Modus \"Wirtschaftlich\" nicht mehr möglich",
"title": "Wissenseinstellungen"
}

View File

@ -31,6 +31,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",
@ -75,6 +76,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",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Pausa",
"list.action.resume": "Reanudar",
"list.action.settings": "Configuración de segmento",
"list.action.summary": "Generar resumen",
"list.action.sync": "Sincronizar",
"list.action.unarchive": "Desarchivar",
"list.action.uploadFile": "Subir nuevo archivo",
@ -75,6 +76,9 @@
"list.status.indexing": "Indexando",
"list.status.paused": "Pausado",
"list.status.queuing": "En cola",
"list.summary.generating": "Generando...",
"list.summary.generatingSummary": "Generando resumen",
"list.summary.ready": "Resumen listo",
"list.table.header.action": "ACCIÓN",
"list.table.header.chunkingMode": "MODO DE FRAGMENTACIÓN",
"list.table.header.fileName": "NOMBRE DEL ARCHIVO",
@ -329,5 +333,7 @@
"segment.searchResults_one": "RESULTADO",
"segment.searchResults_other": "RESULTADOS",
"segment.searchResults_zero": "RESULTADO",
"segment.summary": "RESUMEN",
"segment.summaryPlaceholder": "Escriba un breve resumen para una mejor recuperación…",
"segment.vectorHash": "Hash de vector: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Configuración de recuperación",
"form.save": "Guardar",
"form.searchModel": "Buscar modelo",
"form.summaryAutoGen": "Generación Automática de Resumen",
"form.summaryAutoGenEnableTip": "Una vez habilitado, los resúmenes se generarán automáticamente para documentos recién agregados. Los documentos existentes aún se pueden resumir manualmente.",
"form.summaryAutoGenTip": "Los resúmenes se generan automáticamente para documentos recién agregados. Los documentos existentes aún se pueden resumir manualmente.",
"form.summaryInstructions": "Instrucciones",
"form.summaryInstructionsPlaceholder": "Describa las reglas o el estilo para resúmenes generados automáticamente…",
"form.summaryModel": "Modelo de Resumen",
"form.upgradeHighQualityTip": "Una vez que se actualiza al modo de alta calidad, no está disponible volver al modo económico",
"title": "Configuración del conjunto de datos"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "مکث",
"list.action.resume": "ادامه",
"list.action.settings": "تنظیمات بخش‌بندی",
"list.action.summary": "ایجاد خلاصه",
"list.action.sync": "همگام‌سازی",
"list.action.unarchive": "خارج کردن از بایگانی",
"list.action.uploadFile": "بارگذاری فایل جدید",
@ -75,6 +76,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": "نام فایل",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Pause",
"list.action.resume": "Reprendre",
"list.action.settings": "Paramètres de segment",
"list.action.summary": "Générer un résumé",
"list.action.sync": "Synchroniser",
"list.action.unarchive": "Décompresser",
"list.action.uploadFile": "Télécharger un nouveau fichier",
@ -75,6 +76,9 @@
"list.status.indexing": "Indexation",
"list.status.paused": "En pause",
"list.status.queuing": "Mise en file d'attente",
"list.summary.generating": "Génération...",
"list.summary.generatingSummary": "Génération du résumé",
"list.summary.ready": "Résumé prêt",
"list.table.header.action": "ACTION",
"list.table.header.chunkingMode": "MODE DE MORCEAU",
"list.table.header.fileName": "NOM DU FICHIER",
@ -329,5 +333,7 @@
"segment.searchResults_one": "RÉSULTAT",
"segment.searchResults_other": "RÉSULTATS",
"segment.searchResults_zero": "RÉSULTAT",
"segment.summary": "RÉSUMÉ",
"segment.summaryPlaceholder": "Rédigez un bref résumé pour une meilleure récupération…",
"segment.vectorHash": "Vector hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Paramètres de récupération",
"form.save": "Enregistrer",
"form.searchModel": "Rechercher un modèle",
"form.summaryAutoGen": "Génération Auto de Résumé",
"form.summaryAutoGenEnableTip": "Une fois activé, les résumés seront générés automatiquement pour les documents nouvellement ajoutés. Les documents existants peuvent toujours être résumés manuellement.",
"form.summaryAutoGenTip": "Les résumés sont générés automatiquement pour les documents nouvellement ajoutés. Les documents existants peuvent toujours être résumés manuellement.",
"form.summaryInstructions": "Instructions",
"form.summaryInstructionsPlaceholder": "Décrivez les règles ou le style pour les résumés générés automatiquement…",
"form.summaryModel": "Modèle de Résumé",
"form.upgradeHighQualityTip": "Une fois la mise à niveau vers le mode Haute Qualité, il nest pas possible de revenir au mode Économique",
"title": "Paramètres de connaissance"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "रोकें",
"list.action.resume": "रिज़्यूमे",
"list.action.settings": "खंड सेटिंग्स",
"list.action.summary": "सारांश बनाएं",
"list.action.sync": "सिंक्रोनाइज़ करें",
"list.action.unarchive": "संग्रह से बाहर करें",
"list.action.uploadFile": "नई फाइल अपलोड करें",
@ -75,6 +76,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": "फाइल का नाम",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Jeda",
"list.action.resume": "Melanjutkan",
"list.action.settings": "Pengaturan Chunking",
"list.action.summary": "Buat ringkasan",
"list.action.sync": "Sync",
"list.action.unarchive": "Batalkan arsip",
"list.action.uploadFile": "Unggah file baru",
@ -75,6 +76,9 @@
"list.status.indexing": "Pengindeksan",
"list.status.paused": "Berhenti",
"list.status.queuing": "Antrian",
"list.summary.generating": "Membuat...",
"list.summary.generatingSummary": "Membuat ringkasan",
"list.summary.ready": "Ringkasan siap",
"list.table.header.action": "PERBUATAN",
"list.table.header.chunkingMode": "CHUNKING MODE",
"list.table.header.fileName": "NAMA",
@ -329,5 +333,7 @@
"segment.searchResults_one": "HASIL",
"segment.searchResults_other": "HASIL",
"segment.searchResults_zero": "HASIL",
"segment.summary": "RINGKASAN",
"segment.summaryPlaceholder": "Tulis ringkasan singkat untuk pencarian yang lebih baik…",
"segment.vectorHash": "Hash vektor:"
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Pengaturan Pengambilan",
"form.save": "Simpan",
"form.searchModel": "Model pencarian",
"form.summaryAutoGen": "Pembuatan Ringkasan Otomatis",
"form.summaryAutoGenEnableTip": "Setelah diaktifkan, ringkasan akan dibuat secara otomatis untuk dokumen yang baru ditambahkan. Dokumen yang ada masih dapat diringkas secara manual.",
"form.summaryAutoGenTip": "Ringkasan dibuat secara otomatis untuk dokumen yang baru ditambahkan. Dokumen yang ada masih dapat diringkas secara manual.",
"form.summaryInstructions": "Instruksi",
"form.summaryInstructionsPlaceholder": "Jelaskan aturan atau gaya untuk ringkasan yang dibuat secara otomatis…",
"form.summaryModel": "Model Ringkasan",
"form.upgradeHighQualityTip": "Setelah memutakhirkan ke mode Kualitas Tinggi, kembali ke mode Ekonomis tidak tersedia",
"title": "Setelan pengetahuan"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "Pausa",
"list.action.resume": "Riprendi",
"list.action.settings": "Impostazioni segmenti",
"list.action.summary": "Genera riepilogo",
"list.action.sync": "Sincronizza",
"list.action.unarchive": "Disarchivia",
"list.action.uploadFile": "Carica nuovo file",
@ -75,6 +76,9 @@
"list.status.indexing": "Indicizzazione",
"list.status.paused": "In pausa",
"list.status.queuing": "In coda",
"list.summary.generating": "Generazione...",
"list.summary.generatingSummary": "Generazione riepilogo",
"list.summary.ready": "Riepilogo pronto",
"list.table.header.action": "AZIONE",
"list.table.header.chunkingMode": "MODALITÀ DI SUDDIVISIONE IN BLOCCHI",
"list.table.header.fileName": "NOME FILE",
@ -329,5 +333,7 @@
"segment.searchResults_one": "RISULTATO",
"segment.searchResults_other": "RISULTATI",
"segment.searchResults_zero": "RISULTATO",
"segment.summary": "RIEPILOGO",
"segment.summaryPlaceholder": "Scrivi un breve riepilogo per un migliore recupero…",
"segment.vectorHash": "Hash del vettore: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Impostazioni di recupero",
"form.save": "Salva",
"form.searchModel": "Cerca modello",
"form.summaryAutoGen": "Generazione Automatica Riepilogo",
"form.summaryAutoGenEnableTip": "Una volta abilitato, i riepiloghi verranno generati automaticamente per i documenti appena aggiunti. I documenti esistenti possono ancora essere riassunti manualmente.",
"form.summaryAutoGenTip": "I riepiloghi vengono generati automaticamente per i documenti appena aggiunti. I documenti esistenti possono ancora essere riassunti manualmente.",
"form.summaryInstructions": "Istruzioni",
"form.summaryInstructionsPlaceholder": "Descrivi le regole o lo stile per i riepiloghi generati automaticamente…",
"form.summaryModel": "Modello di Riepilogo",
"form.upgradeHighQualityTip": "Una volta effettuato l'aggiornamento alla modalità Alta qualità, il ripristino della modalità Risparmio non è disponibile",
"title": "Impostazioni della Conoscenza"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "一時停止",
"list.action.resume": "再開",
"list.action.settings": "チャンク設定",
"list.action.summary": "要約を生成",
"list.action.sync": "同期",
"list.action.unarchive": "アーカイブ解除",
"list.action.uploadFile": "新しいファイルをアップロード",
@ -75,6 +76,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": "ファイル名",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "일시 중지",
"list.action.resume": "재개",
"list.action.settings": "세그먼트 설정",
"list.action.summary": "요약 생성",
"list.action.sync": "동기화",
"list.action.unarchive": "아카이브 해제",
"list.action.uploadFile": "새 파일 업로드",
@ -75,6 +76,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": "파일명",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Pauza",
"list.action.resume": "Wznów",
"list.action.settings": "Ustawienia segmentacji",
"list.action.summary": "Wygeneruj podsumowanie",
"list.action.sync": "Synchronizuj",
"list.action.unarchive": "Usuń z archiwum",
"list.action.uploadFile": "Wgraj nowy plik",
@ -75,6 +76,9 @@
"list.status.indexing": "Indeksowanie",
"list.status.paused": "Wstrzymane",
"list.status.queuing": "Oczekiwanie",
"list.summary.generating": "Generowanie...",
"list.summary.generatingSummary": "Generowanie podsumowania",
"list.summary.ready": "Podsumowanie gotowe",
"list.table.header.action": "AKCJA",
"list.table.header.chunkingMode": "TRYB CHUNKINGU",
"list.table.header.fileName": "NAZWA PLIKU",
@ -329,5 +333,7 @@
"segment.searchResults_one": "WYNIK",
"segment.searchResults_other": "WYNIKI",
"segment.searchResults_zero": "WYNIK",
"segment.summary": "PODSUMOWANIE",
"segment.summaryPlaceholder": "Napisz krótkie podsumowanie dla lepszego wyszukiwania…",
"segment.vectorHash": "Wektor hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Ustawienia pobierania",
"form.save": "Zapisz",
"form.searchModel": "Szukaj modelu",
"form.summaryAutoGen": "Automatyczne Generowanie Podsumowania",
"form.summaryAutoGenEnableTip": "Po włączeniu podsumowania będą generowane automatycznie dla nowo dodanych dokumentów. Istniejące dokumenty nadal mogą być podsumowywane ręcznie.",
"form.summaryAutoGenTip": "Podsumowania są generowane automatycznie dla nowo dodanych dokumentów. Istniejące dokumenty nadal mogą być podsumowywane ręcznie.",
"form.summaryInstructions": "Instrukcje",
"form.summaryInstructionsPlaceholder": "Opisz zasady lub styl dla automatycznie generowanych podsumowań…",
"form.summaryModel": "Model Podsumowania",
"form.upgradeHighQualityTip": "Po uaktualnieniu do trybu wysokiej jakości powrót do trybu ekonomicznego nie jest dostępny",
"title": "Ustawienia wiedzy"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "Pausa",
"list.action.resume": "Retomar",
"list.action.settings": "Configurações de segmento",
"list.action.summary": "Gerar resumo",
"list.action.sync": "Sincronizar",
"list.action.unarchive": "Desarquivar",
"list.action.uploadFile": "Enviar novo arquivo",
@ -75,6 +76,9 @@
"list.status.indexing": "Indexando",
"list.status.paused": "Pausado",
"list.status.queuing": "Em fila",
"list.summary.generating": "Gerando...",
"list.summary.generatingSummary": "Gerando resumo",
"list.summary.ready": "Resumo pronto",
"list.table.header.action": "AÇÃO",
"list.table.header.chunkingMode": "MODO DE FRAGMENTAÇÃO",
"list.table.header.fileName": "NOME DO ARQUIVO",
@ -329,5 +333,7 @@
"segment.searchResults_one": "RESULTADO",
"segment.searchResults_other": "RESULTADOS",
"segment.searchResults_zero": "RESULTADO",
"segment.summary": "RESUMO",
"segment.summaryPlaceholder": "Escreva um breve resumo para melhor recuperação…",
"segment.vectorHash": "Hash do vetor: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Configurações de recuperação",
"form.save": "Salvar",
"form.searchModel": "Pesquisar modelo",
"form.summaryAutoGen": "Geração Automática de Resumo",
"form.summaryAutoGenEnableTip": "Uma vez ativado, resumos serão gerados automaticamente para documentos recém-adicionados. Documentos existentes ainda podem ser resumidos manualmente.",
"form.summaryAutoGenTip": "Resumos são gerados automaticamente para documentos recém-adicionados. Documentos existentes ainda podem ser resumidos manualmente.",
"form.summaryInstructions": "Instruções",
"form.summaryInstructionsPlaceholder": "Descreva as regras ou estilo para resumos gerados automaticamente…",
"form.summaryModel": "Modelo de Resumo",
"form.upgradeHighQualityTip": "Depois de atualizar para o modo de alta qualidade, reverter para o modo econômico não está disponível",
"title": "Configurações do conhecimento"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "Pauză",
"list.action.resume": "Reia",
"list.action.settings": "Setări de segment",
"list.action.summary": "Generați rezumat",
"list.action.sync": "Sincronizează",
"list.action.unarchive": "Dezarhivează",
"list.action.uploadFile": "Încarcă un fișier nou",
@ -75,6 +76,9 @@
"list.status.indexing": "Indexare",
"list.status.paused": "Întrerupt",
"list.status.queuing": "În coadă",
"list.summary.generating": "Generare...",
"list.summary.generatingSummary": "Generare rezumat",
"list.summary.ready": "Rezumat gata",
"list.table.header.action": "ACȚIUNE",
"list.table.header.chunkingMode": "MOD DE FRAGMENTARE",
"list.table.header.fileName": "NUMELE FIȘIERULUI",
@ -329,5 +333,7 @@
"segment.searchResults_one": "REZULTAT",
"segment.searchResults_other": "REZULTATELE",
"segment.searchResults_zero": "REZULTAT",
"segment.summary": "REZUMAT",
"segment.summaryPlaceholder": "Scrieți un rezumat scurt pentru o recuperare mai bună…",
"segment.vectorHash": "Vector hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Setări de recuperare",
"form.save": "Salvare",
"form.searchModel": "Căutare model",
"form.summaryAutoGen": "Generare Automată Rezumat",
"form.summaryAutoGenEnableTip": "Odată activat, rezumatele vor fi generate automat pentru documentele nou adăugate. Documentele existente pot fi încă rezumate manual.",
"form.summaryAutoGenTip": "Rezumatele sunt generate automat pentru documentele nou adăugate. Documentele existente pot fi încă rezumate manual.",
"form.summaryInstructions": "Instrucțiuni",
"form.summaryInstructionsPlaceholder": "Descrieți regulile sau stilul pentru rezumatele generate automat…",
"form.summaryModel": "Model Rezumat",
"form.upgradeHighQualityTip": "După ce faceți upgrade la modul Înaltă calitate, revenirea la modul Economic nu este disponibilă",
"title": "Setări de cunoștințe"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "Пауза",
"list.action.resume": "Возобновить",
"list.action.settings": "Настройки сегментации",
"list.action.summary": "Создать резюме",
"list.action.sync": "Синхронизировать",
"list.action.unarchive": "Разархивировать",
"list.action.uploadFile": "Загрузить новый файл",
@ -75,6 +76,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": "НАЗВАНИЕ ФАЙЛА",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Zaustavi",
"list.action.resume": "Nadaljuj",
"list.action.settings": "Nastavitve segmenta",
"list.action.summary": "Ustvari povzetek",
"list.action.sync": "Sinhroniziraj",
"list.action.unarchive": "Razveljavi arhiviranje",
"list.action.uploadFile": "Naloži novo datoteko",
@ -75,6 +76,9 @@
"list.status.indexing": "Indeksiranje",
"list.status.paused": "Zaustavljeno",
"list.status.queuing": "V čakalni vrsti",
"list.summary.generating": "Ustvarjanje...",
"list.summary.generatingSummary": "Ustvarjanje povzetka",
"list.summary.ready": "Povzetek pripravljen",
"list.table.header.action": "DEJANJE",
"list.table.header.chunkingMode": "NAČIN KOŠČENJA",
"list.table.header.fileName": "IME DATOTEKE",
@ -329,5 +333,7 @@
"segment.searchResults_one": "REZULTAT",
"segment.searchResults_other": "REZULTATI",
"segment.searchResults_zero": "REZULTAT",
"segment.summary": "POVZETEK",
"segment.summaryPlaceholder": "Napišite kratek povzetek za boljše iskanje…",
"segment.vectorHash": "Vektorski hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Nastavitve pridobivanja",
"form.save": "Shrani",
"form.searchModel": "Išči model",
"form.summaryAutoGen": "Samodejna Tvorba Povzetka",
"form.summaryAutoGenEnableTip": "Ko je omogočeno, bodo povzetki samodejno ustvarjeni za novo dodane dokumente. Obstoječe dokumente lahko še vedno povzamete ročno.",
"form.summaryAutoGenTip": "Povzetki so samodejno ustvarjeni za novo dodane dokumente. Obstoječe dokumente lahko še vedno povzamete ročno.",
"form.summaryInstructions": "Navodila",
"form.summaryInstructionsPlaceholder": "Opišite pravila ali slog za samodejno ustvarjene povzetke…",
"form.summaryModel": "Model Povzetka",
"form.upgradeHighQualityTip": "Ko nadgradite na način visoke kakovosti, vrnitev v ekonomični način ni na voljo",
"title": "Nastavitve znanja"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "หยุด",
"list.action.resume": "ดำเนิน",
"list.action.settings": "การตั้งค่ากลุ่ม",
"list.action.summary": "สร้างสรุป",
"list.action.sync": "ซิงค์",
"list.action.unarchive": "ยกเลิกการเก็บถาวร",
"list.action.uploadFile": "อัปโหลดไฟล์ใหม่",
@ -75,6 +76,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": "ชื่อไฟล์",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Duraklat",
"list.action.resume": "Devam Et",
"list.action.settings": "Segment ayarları",
"list.action.summary": "Özet oluştur",
"list.action.sync": "Senkronize et",
"list.action.unarchive": "Arşivden Çıkar",
"list.action.uploadFile": "Yeni dosya yükle",
@ -75,6 +76,9 @@
"list.status.indexing": "Dizine Ekleniyor",
"list.status.paused": "Durduruldu",
"list.status.queuing": "Kuyrukta",
"list.summary.generating": "Oluşturuluyor...",
"list.summary.generatingSummary": "Özet oluşturuluyor",
"list.summary.ready": "Özet hazır",
"list.table.header.action": "EYLEM",
"list.table.header.chunkingMode": "PARÇALAMA MODU",
"list.table.header.fileName": "DOSYA ADI",
@ -329,5 +333,7 @@
"segment.searchResults_one": "SONUÇ",
"segment.searchResults_other": "SONUÇ -LARI",
"segment.searchResults_zero": "SONUÇ",
"segment.summary": "ÖZET",
"segment.summaryPlaceholder": "Daha iyi arama için kısa bir özet yazın…",
"segment.vectorHash": "Vektör hash: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Alma Ayarları",
"form.save": "Kaydet",
"form.searchModel": "Model Ara",
"form.summaryAutoGen": "Özet Otomatik Oluşturma",
"form.summaryAutoGenEnableTip": "Etkinleştirildiğinde, yeni eklenen belgeler için özetler otomatik olarak oluşturulacaktır. Mevcut belgeler hala manuel olarak özetlenebilir.",
"form.summaryAutoGenTip": "Yeni eklenen belgeler için özetler otomatik olarak oluşturulur. Mevcut belgeler hala manuel olarak özetlenebilir.",
"form.summaryInstructions": "Talimatlar",
"form.summaryInstructionsPlaceholder": "Otomatik oluşturulan özetler için kuralları veya stili açıklayın…",
"form.summaryModel": "Özet Modeli",
"form.upgradeHighQualityTip": "Yüksek Kalite moduna yükselttikten sonra Ekonomik moda geri dönülemez",
"title": "Bilgi ayarları"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "Пауза",
"list.action.resume": "Продовжити",
"list.action.settings": "Налаштування сегмента",
"list.action.summary": "Створити резюме",
"list.action.sync": "Синхронізувати",
"list.action.unarchive": "Розархівувати",
"list.action.uploadFile": "Завантажити новий файл",
@ -75,6 +76,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": "НАЗВА ФАЙЛУ",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "Tạm dừng",
"list.action.resume": "Tiếp tục",
"list.action.settings": "Cài đặt phân đoạn",
"list.action.summary": "Tạo tóm tắt",
"list.action.sync": "Đồng bộ",
"list.action.unarchive": "Khôi phục",
"list.action.uploadFile": "Tải lên tệp mới",
@ -75,6 +76,9 @@
"list.status.indexing": "Đang lập chỉ mục",
"list.status.paused": "Tạm dừng",
"list.status.queuing": "Đang chờ",
"list.summary.generating": "Đang tạo...",
"list.summary.generatingSummary": "Đang tạo tóm tắt",
"list.summary.ready": "Tóm tắt đã sẵn sàng",
"list.table.header.action": "THAO TÁC",
"list.table.header.chunkingMode": "CHẾ ĐỘ CHUNKING",
"list.table.header.fileName": "TÊN TỆP",
@ -329,5 +333,7 @@
"segment.searchResults_one": "KẾT QUẢ",
"segment.searchResults_other": "KẾT QUẢ",
"segment.searchResults_zero": "KẾT QUẢ",
"segment.summary": "TÓM TẮT",
"segment.summaryPlaceholder": "Viết tóm tắt ngắn gọn để tìm kiếm tốt hơn…",
"segment.vectorHash": "Mã băm vector: "
}

View File

@ -39,6 +39,12 @@
"form.retrievalSettings": "Cài đặt truy xuất",
"form.save": "Lưu",
"form.searchModel": "Tìm kiếm mô hình",
"form.summaryAutoGen": "Tự động Tạo Tóm tắt",
"form.summaryAutoGenEnableTip": "Sau khi bật, tóm tắt sẽ được tạo tự động cho các tài liệu mới được thêm. Các tài liệu hiện có vẫn có thể được tóm tắt thủ công.",
"form.summaryAutoGenTip": "Tóm tắt được tạo tự động cho các tài liệu mới được thêm. Các tài liệu hiện có vẫn có thể được tóm tắt thủ công.",
"form.summaryInstructions": "Hướng dẫn",
"form.summaryInstructionsPlaceholder": "Mô tả các quy tắc hoặc phong cách cho tóm tắt được tạo tự động…",
"form.summaryModel": "Mô hình Tóm tắt",
"form.upgradeHighQualityTip": "Sau khi nâng cấp lên chế độ Chất lượng cao, không thể hoàn nguyên về chế độ Tiết kiệm",
"title": "Cài đặt Kiến thức"
}

View File

@ -31,6 +31,7 @@
"list.action.pause": "暂停",
"list.action.resume": "恢复",
"list.action.settings": "分段设置",
"list.action.summary": "生成摘要",
"list.action.sync": "同步",
"list.action.unarchive": "撤销归档",
"list.action.uploadFile": "上传新文件",
@ -75,6 +76,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": "名称",
@ -329,5 +333,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

@ -31,6 +31,7 @@
"list.action.pause": "暫停",
"list.action.resume": "恢復",
"list.action.settings": "分段設定",
"list.action.summary": "產生摘要",
"list.action.sync": "同步",
"list.action.unarchive": "撤銷歸檔",
"list.action.uploadFile": "上傳新檔案",
@ -75,6 +76,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": "檔名",
@ -329,5 +333,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 = {
@ -225,7 +233,7 @@ export type IndexingEstimateResponse = {
total_price: number
currency: string
total_segments: number
preview: Array<{ content: string, child_chunks: string[] }>
preview: Array<{ content: string, child_chunks: string[], summary?: string }>
qa_preview?: QA[]
}
@ -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) => {