mirror of https://github.com/langgenius/dify.git
refactor: Update knowledge pipeline terminology and chunk detail UI/UX (#25749)
This commit is contained in:
commit
1e9fce50a1
|
|
@ -8,6 +8,7 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
|||
import type { FullDocumentDetail, createDocumentResponse } from '@/models/datasets'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
|
||||
type StepThreeProps = {
|
||||
datasetId?: string
|
||||
|
|
@ -19,6 +20,7 @@ type StepThreeProps = {
|
|||
|
||||
const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrievalMethod }: StepThreeProps) => {
|
||||
const { t } = useTranslation()
|
||||
const docLink = useDocLink()
|
||||
|
||||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
|
|
@ -83,6 +85,14 @@ const StepThree = ({ datasetId, datasetName, indexingType, creationCache, retrie
|
|||
</div>
|
||||
<div className='text-base font-semibold text-text-secondary'>{t('datasetCreation.stepThree.sideTipTitle')}</div>
|
||||
<div className='text-text-tertiary'>{t('datasetCreation.stepThree.sideTipContent')}</div>
|
||||
<a
|
||||
href={docLink('/guides/knowledge-base/integrate-knowledge-within-application')}
|
||||
target='_blank'
|
||||
rel='noreferrer noopener'
|
||||
className='system-sm-regular text-text-accent'
|
||||
>
|
||||
{t('datasetPipeline.addDocuments.stepThree.learnMore')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { useModalContextSelector } from '@/context/modal-context'
|
|||
import Title from './title'
|
||||
import { useGetDataSourceAuth } from '@/service/use-datasource'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
|
||||
type OnlineDocumentsProps = {
|
||||
isInPipeline?: boolean
|
||||
|
|
@ -29,6 +30,7 @@ const OnlineDocuments = ({
|
|||
isInPipeline = false,
|
||||
onCredentialChange,
|
||||
}: OnlineDocumentsProps) => {
|
||||
const docLink = useDocLink()
|
||||
const pipelineId = useDatasetDetailContextWithSelector(s => s.dataset?.pipeline_id)
|
||||
const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal)
|
||||
const {
|
||||
|
|
@ -125,8 +127,8 @@ const OnlineDocuments = ({
|
|||
return (
|
||||
<div className='flex flex-col gap-y-2'>
|
||||
<Header
|
||||
docTitle='How to use?'
|
||||
docLink='https://docs.dify.ai'
|
||||
docTitle='Docs'
|
||||
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
|
||||
onClickConfiguration={handleSetting}
|
||||
pluginName={nodeData.datasource_label}
|
||||
currentCredentialId={currentCredentialId}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import produce from 'immer'
|
|||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useGetDataSourceAuth } from '@/service/use-datasource'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
|
||||
type OnlineDriveProps = {
|
||||
nodeId: string
|
||||
|
|
@ -28,6 +29,7 @@ const OnlineDrive = ({
|
|||
isInPipeline = false,
|
||||
onCredentialChange,
|
||||
}: OnlineDriveProps) => {
|
||||
const docLink = useDocLink()
|
||||
const [isInitialMount, setIsInitialMount] = useState(true)
|
||||
const pipelineId = useDatasetDetailContextWithSelector(s => s.dataset?.pipeline_id)
|
||||
const setShowAccountSettingModal = useModalContextSelector(s => s.setShowAccountSettingModal)
|
||||
|
|
@ -185,8 +187,8 @@ const OnlineDrive = ({
|
|||
return (
|
||||
<div className='flex flex-col gap-y-2'>
|
||||
<Header
|
||||
docTitle='Online Drive Docs'
|
||||
docLink='https://docs.dify.ai/'
|
||||
docTitle='Docs'
|
||||
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
|
||||
onClickConfiguration={handleSetting}
|
||||
pluginName={nodeData.datasource_label}
|
||||
currentCredentialId={currentCredentialId}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { useDataSourceStore, useDataSourceStoreWithSelector } from '../store'
|
|||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useGetDataSourceAuth } from '@/service/use-datasource'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
|
||||
const I18N_PREFIX = 'datasetCreation.stepOne.website'
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ const WebsiteCrawl = ({
|
|||
onCredentialChange,
|
||||
}: WebsiteCrawlProps) => {
|
||||
const { t } = useTranslation()
|
||||
const docLink = useDocLink()
|
||||
const [totalNum, setTotalNum] = useState(0)
|
||||
const [crawledNum, setCrawledNum] = useState(0)
|
||||
const [crawlErrorMessage, setCrawlErrorMessage] = useState('')
|
||||
|
|
@ -151,8 +153,8 @@ const WebsiteCrawl = ({
|
|||
return (
|
||||
<div className='flex flex-col'>
|
||||
<Header
|
||||
docTitle='How to use?'
|
||||
docLink='https://docs.dify.ai'
|
||||
docTitle='Docs'
|
||||
docLink={docLink('/guides/knowledge-base/knowledge-pipeline/authorize-data-source')}
|
||||
onClickConfiguration={handleSetting}
|
||||
pluginName={nodeData.datasource_label}
|
||||
currentCredentialId={currentCredentialId}
|
||||
|
|
|
|||
|
|
@ -95,12 +95,13 @@ const ChildSegmentList: FC<IChildSegmentCardProps> = ({
|
|||
)}>
|
||||
{isFullDocMode ? <Divider type='horizontal' className='my-1 h-px bg-divider-subtle' /> : null}
|
||||
<div className={cn('flex items-center justify-between', isFullDocMode ? 'sticky -top-2 left-0 bg-background-default pb-3 pt-2' : '')}>
|
||||
<div className={cn(
|
||||
'flex h-7 items-center rounded-lg pl-1 pr-3',
|
||||
isParagraphMode && 'cursor-pointer',
|
||||
(isParagraphMode && collapsed) && 'bg-dataset-child-chunk-expand-btn-bg',
|
||||
isFullDocMode && 'pl-0',
|
||||
)}
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-7 items-center rounded-lg pl-1 pr-3',
|
||||
isParagraphMode && 'cursor-pointer',
|
||||
(isParagraphMode && collapsed) && 'bg-dataset-child-chunk-expand-btn-bg',
|
||||
isFullDocMode && 'pl-0',
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
toggleCollapse()
|
||||
|
|
@ -162,6 +163,7 @@ const ChildSegmentList: FC<IChildSegmentCardProps> = ({
|
|||
label={`C-${childChunk.position}${edited ? ` · ${t('datasetDocuments.segment.edited')}` : ''}`}
|
||||
text={childChunk.content}
|
||||
onDelete={() => onDelete?.(childChunk.segment_id, childChunk.id)}
|
||||
className='child-chunk'
|
||||
labelClassName={focused ? 'bg-state-accent-solid text-text-primary-on-surface' : ''}
|
||||
labelInnerClassName={'text-[10px] font-semibold align-bottom leading-6'}
|
||||
contentClassName={cn('!leading-6', focused ? 'bg-state-accent-hover-alt text-text-primary' : 'text-text-secondary')}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
import React, { useCallback, useEffect, useRef } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useKeyPress } from 'ahooks'
|
||||
import { useSegmentListContext } from '..'
|
||||
|
||||
type DrawerProps = {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
side?: 'right' | 'left' | 'bottom' | 'top'
|
||||
showOverlay?: boolean
|
||||
modal?: boolean // click outside event can pass through if modal is false
|
||||
closeOnOutsideClick?: boolean
|
||||
panelClassName?: string
|
||||
panelContentClassName?: string
|
||||
needCheckChunks?: boolean
|
||||
}
|
||||
|
||||
const Drawer = ({
|
||||
open,
|
||||
onClose,
|
||||
side = 'right',
|
||||
showOverlay = true,
|
||||
modal = false,
|
||||
needCheckChunks = false,
|
||||
children,
|
||||
panelClassName,
|
||||
panelContentClassName,
|
||||
}: React.PropsWithChildren<DrawerProps>) => {
|
||||
const panelContentRef = useRef<HTMLDivElement>(null)
|
||||
const currSegment = useSegmentListContext(s => s.currSegment)
|
||||
const currChildChunk = useSegmentListContext(s => s.currChildChunk)
|
||||
|
||||
useKeyPress('esc', (e) => {
|
||||
if (!open) return
|
||||
e.preventDefault()
|
||||
onClose()
|
||||
}, { exactMatch: true, useCapture: true })
|
||||
|
||||
const shouldCloseDrawer = useCallback((target: Node | null) => {
|
||||
const panelContent = panelContentRef.current
|
||||
if (!panelContent) return false
|
||||
const chunks = document.querySelectorAll('.chunk-card')
|
||||
const childChunks = document.querySelectorAll('.child-chunk')
|
||||
const isClickOnChunk = Array.from(chunks).some((chunk) => {
|
||||
return chunk && chunk.contains(target)
|
||||
})
|
||||
const isClickOnChildChunk = Array.from(childChunks).some((chunk) => {
|
||||
return chunk && chunk.contains(target)
|
||||
})
|
||||
const reopenChunkDetail = (currSegment.showModal && isClickOnChildChunk)
|
||||
|| (currChildChunk.showModal && isClickOnChunk && !isClickOnChildChunk)
|
||||
return target && !panelContent.contains(target) && (!needCheckChunks || reopenChunkDetail)
|
||||
}, [currSegment, currChildChunk, needCheckChunks])
|
||||
|
||||
const onDownCapture = useCallback((e: PointerEvent) => {
|
||||
if (!open || modal) return
|
||||
const panelContent = panelContentRef.current
|
||||
if (!panelContent) return
|
||||
const target = e.target as Node | null
|
||||
if (shouldCloseDrawer(target))
|
||||
queueMicrotask(onClose)
|
||||
}, [shouldCloseDrawer, onClose, open, modal])
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('pointerdown', onDownCapture, { capture: true })
|
||||
return () =>
|
||||
window.removeEventListener('pointerdown', onDownCapture, { capture: true })
|
||||
}, [onDownCapture])
|
||||
|
||||
const isHorizontal = side === 'left' || side === 'right'
|
||||
|
||||
const content = (
|
||||
<div className='pointer-events-none fixed inset-0 z-[9999]'>
|
||||
{showOverlay ? (
|
||||
<div
|
||||
onClick={modal ? onClose : undefined}
|
||||
aria-hidden='true'
|
||||
className={cn(
|
||||
'fixed inset-0 bg-black/30 opacity-0 transition-opacity duration-200 ease-in',
|
||||
open && 'opacity-100',
|
||||
modal && open ? 'pointer-events-auto' : 'pointer-events-none',
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{/* Drawer panel */}
|
||||
<div
|
||||
role='dialog'
|
||||
aria-modal={modal ? 'true' : 'false'}
|
||||
className={cn(
|
||||
'pointer-events-auto fixed flex flex-col',
|
||||
side === 'right' && 'right-0',
|
||||
side === 'left' && 'left-0',
|
||||
side === 'bottom' && 'bottom-0',
|
||||
side === 'top' && 'top-0',
|
||||
isHorizontal ? 'h-screen' : 'w-screen',
|
||||
panelClassName,
|
||||
)}
|
||||
>
|
||||
<div ref={panelContentRef} className={cn('flex grow flex-col', panelContentClassName)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return open && createPortal(content, document.body)
|
||||
}
|
||||
|
||||
export default Drawer
|
||||
|
|
@ -1,33 +1,42 @@
|
|||
import React, { type FC } from 'react'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import classNames from '@/utils/classnames'
|
||||
import React from 'react'
|
||||
import Drawer from './drawer'
|
||||
import cn from '@/utils/classnames'
|
||||
import { noop } from 'lodash-es'
|
||||
|
||||
type IFullScreenDrawerProps = {
|
||||
isOpen: boolean
|
||||
onClose?: () => void
|
||||
fullScreen: boolean
|
||||
children: React.ReactNode
|
||||
showOverlay?: boolean
|
||||
needCheckChunks?: boolean
|
||||
modal?: boolean
|
||||
}
|
||||
|
||||
const FullScreenDrawer: FC<IFullScreenDrawerProps> = ({
|
||||
const FullScreenDrawer = ({
|
||||
isOpen,
|
||||
onClose = noop,
|
||||
fullScreen,
|
||||
children,
|
||||
}) => {
|
||||
showOverlay = true,
|
||||
needCheckChunks = false,
|
||||
modal = false,
|
||||
}: React.PropsWithChildren<IFullScreenDrawerProps>) => {
|
||||
return (
|
||||
<Drawer
|
||||
isOpen={isOpen}
|
||||
open={isOpen}
|
||||
onClose={onClose}
|
||||
panelClassName={classNames('bg-components-panel-bg !p-0',
|
||||
panelClassName={cn(
|
||||
fullScreen
|
||||
? '!w-full !max-w-full'
|
||||
: 'mb-2 mr-2 mt-16 !w-[560px] !max-w-[560px] rounded-xl border-[0.5px] border-components-panel-border',
|
||||
? 'w-full'
|
||||
: 'w-[560px] pb-2 pr-2 pt-16',
|
||||
)}
|
||||
mask={false}
|
||||
unmount
|
||||
footer={null}
|
||||
panelContentClassName={cn(
|
||||
'bg-components-panel-bg',
|
||||
!fullScreen && 'rounded-xl border-[0.5px] border-components-panel-border',
|
||||
)}
|
||||
showOverlay={showOverlay}
|
||||
needCheckChunks={needCheckChunks}
|
||||
modal={modal}
|
||||
>
|
||||
{children}
|
||||
</Drawer>)
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
return docForm === ChunkingMode.parentChild && parentMode === 'full-doc'
|
||||
}, [docForm, parentMode])
|
||||
|
||||
const { isFetching: isLoadingSegmentList, data: segmentListData } = useSegmentList(
|
||||
const { isLoading: isLoadingSegmentList, data: segmentListData } = useSegmentList(
|
||||
{
|
||||
datasetId,
|
||||
documentId,
|
||||
|
|
@ -183,7 +183,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
}
|
||||
}, [segments])
|
||||
|
||||
const { isFetching: isLoadingChildSegmentList, data: childChunkListData } = useChildSegmentList(
|
||||
const { isLoading: isLoadingChildSegmentList, data: childChunkListData } = useChildSegmentList(
|
||||
{
|
||||
datasetId,
|
||||
documentId,
|
||||
|
|
@ -664,8 +664,11 @@ const Completed: FC<ICompletedProps> = ({
|
|||
isOpen={currSegment.showModal}
|
||||
fullScreen={fullScreen}
|
||||
onClose={onCloseSegmentDetail}
|
||||
showOverlay={false}
|
||||
needCheckChunks
|
||||
>
|
||||
<SegmentDetail
|
||||
key={currSegment.segInfo?.id}
|
||||
segInfo={currSegment.segInfo ?? { id: '' }}
|
||||
docForm={docForm}
|
||||
isEditMode={currSegment.isEditMode}
|
||||
|
|
@ -678,6 +681,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
isOpen={showNewSegmentModal}
|
||||
fullScreen={fullScreen}
|
||||
onClose={onCloseNewSegmentModal}
|
||||
modal
|
||||
>
|
||||
<NewSegment
|
||||
docForm={docForm}
|
||||
|
|
@ -691,8 +695,11 @@ const Completed: FC<ICompletedProps> = ({
|
|||
isOpen={currChildChunk.showModal}
|
||||
fullScreen={fullScreen}
|
||||
onClose={onCloseChildSegmentDetail}
|
||||
showOverlay={false}
|
||||
needCheckChunks
|
||||
>
|
||||
<ChildSegmentDetail
|
||||
key={currChildChunk.childChunkInfo?.id}
|
||||
chunkId={currChunkId}
|
||||
childChunkInfo={currChildChunk.childChunkInfo ?? { id: '' }}
|
||||
docForm={docForm}
|
||||
|
|
@ -705,6 +712,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||
isOpen={showNewChildSegmentModal}
|
||||
fullScreen={fullScreen}
|
||||
onClose={onCloseNewChildChunkModal}
|
||||
modal
|
||||
>
|
||||
<NewChildSegment
|
||||
chunkId={currChunkId}
|
||||
|
|
@ -714,15 +722,16 @@ const Completed: FC<ICompletedProps> = ({
|
|||
/>
|
||||
</FullScreenDrawer>
|
||||
{/* Batch Action Buttons */}
|
||||
{selectedSegmentIds.length > 0
|
||||
&& <BatchAction
|
||||
{selectedSegmentIds.length > 0 && (
|
||||
<BatchAction
|
||||
className='absolute bottom-16 left-0 z-20'
|
||||
selectedIds={selectedSegmentIds}
|
||||
onBatchEnable={onChangeSwitch.bind(null, true, '')}
|
||||
onBatchDisable={onChangeSwitch.bind(null, false, '')}
|
||||
onBatchDelete={onDelete.bind(null, '')}
|
||||
onCancel={onCancelBatchOperation}
|
||||
/>}
|
||||
/>
|
||||
)}
|
||||
</SegmentListContext.Provider>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'group/card w-full rounded-xl px-3',
|
||||
'chunk-card group/card w-full rounded-xl px-3',
|
||||
isFullDocMode ? '' : 'pb-2 pt-2.5 hover:bg-dataset-chunk-detail-card-hover-bg',
|
||||
focused.segmentContent ? 'bg-dataset-chunk-detail-card-hover-bg' : '',
|
||||
className,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ const Popup = () => {
|
|||
const { mutateAsync: publishWorkflow } = usePublishWorkflow()
|
||||
const { notify } = useToastContext()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { isAllowPublishAsKnowledgePipeline } = useProviderContext()
|
||||
const { isAllowPublishAsCustomKnowledgePipelineTemplate } = useProviderContext()
|
||||
const setShowPricingModal = useModalContextSelector(s => s.setShowPricingModal)
|
||||
|
||||
const [confirmVisible, {
|
||||
|
|
@ -206,16 +206,16 @@ const Popup = () => {
|
|||
])
|
||||
|
||||
const handleClickPublishAsKnowledgePipeline = useCallback(() => {
|
||||
if (!isAllowPublishAsKnowledgePipeline)
|
||||
if (!isAllowPublishAsCustomKnowledgePipelineTemplate)
|
||||
setShowPricingModal()
|
||||
else
|
||||
setShowPublishAsKnowledgePipelineModal()
|
||||
}, [isAllowPublishAsKnowledgePipeline, setShowPublishAsKnowledgePipelineModal, setShowPricingModal])
|
||||
}, [isAllowPublishAsCustomKnowledgePipelineTemplate, setShowPublishAsKnowledgePipelineModal, setShowPricingModal])
|
||||
|
||||
return (
|
||||
<div className={classNames(
|
||||
'rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl shadow-shadow-shadow-5',
|
||||
isAllowPublishAsKnowledgePipeline ? 'w-[320px] ' : 'w-[360px]',
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate ? 'w-[360px]' : 'w-[400px]',
|
||||
)}>
|
||||
<div className='p-4 pt-3'>
|
||||
<div className='system-xs-medium-uppercase flex h-6 items-center text-text-tertiary'>
|
||||
|
|
@ -293,12 +293,12 @@ const Popup = () => {
|
|||
onClick={handleClickPublishAsKnowledgePipeline}
|
||||
disabled={!publishedAt || isPublishingAsCustomizedPipeline}
|
||||
>
|
||||
<div className='flex grow items-center gap-x-2'>
|
||||
<div className='flex grow items-center gap-x-2 overflow-hidden'>
|
||||
<RiHammerLine className='h-4 w-4 shrink-0' />
|
||||
<span className='grow truncate text-left' title={t('pipeline.common.publishAs')}>
|
||||
{t('pipeline.common.publishAs')}
|
||||
</span>
|
||||
{!isAllowPublishAsKnowledgePipeline && (
|
||||
{!isAllowPublishAsCustomKnowledgePipelineTemplate && (
|
||||
<PremiumBadge className='shrink-0 cursor-pointer select-none' size='s' color='indigo'>
|
||||
<SparklesSoft className='flex size-3 items-center text-components-premium-badge-indigo-text-stop-0' />
|
||||
<span className='system-2xs-medium p-0.5'>
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ export const useAvailableNodesMetaData = () => {
|
|||
dataSourceEmptyDefault,
|
||||
], [])
|
||||
|
||||
const prefixLink = useMemo(() => {
|
||||
const helpLinkUri = useMemo(() => {
|
||||
if (language === 'zh_Hans')
|
||||
return 'https://docs.dify.ai/zh-hans/guides/workflow/node/'
|
||||
return 'https://docs.dify.ai/zh-hans/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#%E6%AD%A5%E9%AA%A4%E4%B8%80%EF%BC%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E9%85%8D%E7%BD%AE'
|
||||
if (language === 'ja_JP')
|
||||
return 'https://docs.dify.ai/ja-jp/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#%E3%82%B9%E3%83%86%E3%83%83%E3%83%971%EF%BC%9A%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A'
|
||||
|
||||
return 'https://docs.dify.ai/guides/workflow/node/'
|
||||
return 'https://docs.dify.ai/en/guides/knowledge-base/knowledge-pipeline/knowledge-pipeline-orchestration#step-1%3A-data-source'
|
||||
}, [language])
|
||||
|
||||
const availableNodesMetaData = useMemo(() => mergedNodesMetaData.map((node) => {
|
||||
|
|
@ -42,7 +44,7 @@ export const useAvailableNodesMetaData = () => {
|
|||
...metaData,
|
||||
title,
|
||||
description,
|
||||
helpLinkUri: `${prefixLink}${metaData.helpLinkUri}`,
|
||||
helpLinkUri,
|
||||
},
|
||||
defaultValue: {
|
||||
...node.defaultValue,
|
||||
|
|
@ -50,7 +52,7 @@ export const useAvailableNodesMetaData = () => {
|
|||
title,
|
||||
},
|
||||
}
|
||||
}), [mergedNodesMetaData, t, prefixLink])
|
||||
}), [mergedNodesMetaData, t])
|
||||
|
||||
const availableNodesMetaDataMap = useMemo(() => availableNodesMetaData.reduce((acc, node) => {
|
||||
acc![node.metaData.type] = node
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ const RerankingModelSelector = ({
|
|||
readonly = false,
|
||||
}: RerankingModelSelectorProps) => {
|
||||
const {
|
||||
modelList: rerankModelList,
|
||||
} = useModelListAndDefaultModel(ModelTypeEnum.rerank)
|
||||
modelList: rerankModelList,
|
||||
} = useModelListAndDefaultModel(ModelTypeEnum.rerank)
|
||||
const rerankModel = useMemo(() => {
|
||||
if (!rerankingModel)
|
||||
return undefined
|
||||
|
|
|
|||
|
|
@ -178,11 +178,13 @@ const SearchMethodOption = ({
|
|||
</div>
|
||||
)
|
||||
}
|
||||
<RerankingModelSelector
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
{rerankingModelEnabled && (
|
||||
<RerankingModelSelector
|
||||
rerankingModel={rerankingModel}
|
||||
onRerankingModelChange={onRerankingModelChange}
|
||||
readonly={readonly}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,16 @@ export const useConfig = (id: string) => {
|
|||
})
|
||||
}, [getNodeData, handleNodeDataUpdate])
|
||||
|
||||
const handleRerankingModelEnabledChange = useCallback((rerankingModelEnabled: boolean) => {
|
||||
const nodeData = getNodeData()
|
||||
handleNodeDataUpdate({
|
||||
retrieval_model: {
|
||||
...nodeData?.data.retrieval_model,
|
||||
reranking_enable: rerankingModelEnabled,
|
||||
},
|
||||
})
|
||||
}, [getNodeData, handleNodeDataUpdate])
|
||||
|
||||
const handleWeighedScoreChange = useCallback((weightedScore: { value: number[] }) => {
|
||||
const nodeData = getNodeData()
|
||||
handleNodeDataUpdate({
|
||||
|
|
@ -190,6 +200,7 @@ export const useConfig = (id: string) => {
|
|||
handleEmbeddingModelChange,
|
||||
handleRetrievalSearchMethodChange,
|
||||
handleHybridSearchModeChange,
|
||||
handleRerankingModelEnabledChange,
|
||||
handleWeighedScoreChange,
|
||||
handleRerankingModelChange,
|
||||
handleTopKChange,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
|||
handleEmbeddingModelChange,
|
||||
handleRetrievalSearchMethodChange,
|
||||
handleHybridSearchModeChange,
|
||||
handleRerankingModelEnabledChange,
|
||||
handleWeighedScoreChange,
|
||||
handleRerankingModelChange,
|
||||
handleTopKChange,
|
||||
|
|
@ -150,6 +151,8 @@ const Panel: FC<NodePanelProps<KnowledgeBaseNodeType>> = ({
|
|||
onHybridSearchModeChange={handleHybridSearchModeChange}
|
||||
weightedScore={data.retrieval_model.weights}
|
||||
onWeightedScoreChange={handleWeighedScoreChange}
|
||||
rerankingModelEnabled={data.retrieval_model.reranking_enable}
|
||||
onRerankingModelEnabledChange={handleRerankingModelEnabledChange}
|
||||
rerankingModel={data.retrieval_model.reranking_model}
|
||||
onRerankingModelChange={handleRerankingModelChange}
|
||||
topK={data.retrieval_model.top_k}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ type ProviderContextState = {
|
|||
},
|
||||
refreshLicenseLimit: () => void
|
||||
isAllowTransferWorkspace: boolean
|
||||
isAllowPublishAsKnowledgePipeline: boolean
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: boolean
|
||||
}
|
||||
const ProviderContext = createContext<ProviderContextState>({
|
||||
modelProviders: [],
|
||||
|
|
@ -108,7 +108,7 @@ const ProviderContext = createContext<ProviderContextState>({
|
|||
},
|
||||
refreshLicenseLimit: noop,
|
||||
isAllowTransferWorkspace: false,
|
||||
isAllowPublishAsKnowledgePipeline: false,
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate: false,
|
||||
})
|
||||
|
||||
export const useProviderContext = () => useContext(ProviderContext)
|
||||
|
|
@ -147,7 +147,7 @@ export const ProviderContextProvider = ({
|
|||
const [isEducationWorkspace, setIsEducationWorkspace] = useState(false)
|
||||
const { data: educationAccountInfo, isLoading: isLoadingEducationAccountInfo, isFetching: isFetchingEducationAccountInfo } = useEducationStatus(!enableEducationPlan)
|
||||
const [isAllowTransferWorkspace, setIsAllowTransferWorkspace] = useState(false)
|
||||
const [isAllowPublishAsKnowledgePipeline, setIsAllowPublishAsKnowledgePipeline] = useState(false)
|
||||
const [isAllowPublishAsCustomKnowledgePipelineTemplate, setIsAllowPublishAsCustomKnowledgePipelineTemplate] = useState(false)
|
||||
|
||||
const fetchPlan = async () => {
|
||||
try {
|
||||
|
|
@ -179,7 +179,7 @@ export const ProviderContextProvider = ({
|
|||
if (data.is_allow_transfer_workspace)
|
||||
setIsAllowTransferWorkspace(data.is_allow_transfer_workspace)
|
||||
if (data.knowledge_pipeline?.publish_enabled)
|
||||
setIsAllowPublishAsKnowledgePipeline(data.knowledge_pipeline?.publish_enabled)
|
||||
setIsAllowPublishAsCustomKnowledgePipelineTemplate(data.knowledge_pipeline?.publish_enabled)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to fetch plan info:', error)
|
||||
|
|
@ -245,7 +245,7 @@ export const ProviderContextProvider = ({
|
|||
licenseLimit,
|
||||
refreshLicenseLimit: fetchPlan,
|
||||
isAllowTransferWorkspace,
|
||||
isAllowPublishAsKnowledgePipeline,
|
||||
isAllowPublishAsCustomKnowledgePipelineTemplate,
|
||||
}}>
|
||||
{children}
|
||||
</ProviderContext.Provider>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const translation = {
|
||||
common: {
|
||||
goToAddDocuments: 'Go to add documents',
|
||||
publishAs: 'Publish as a Knowledge Pipeline',
|
||||
publishAs: 'Publish as a Customized Pipeline Template',
|
||||
confirmPublish: 'Confirm Publish',
|
||||
confirmPublishContent: 'After successfully publishing the knowledge pipeline, the chunk structure of this knowledge base cannot be modified. Are you sure you want to publish it?',
|
||||
publishAsPipeline: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const translation = {
|
||||
common: {
|
||||
goToAddDocuments: '去添加文档',
|
||||
publishAs: '发布为知识流水线',
|
||||
publishAs: '发布为自定义流水线模板',
|
||||
confirmPublish: '确认发布',
|
||||
confirmPublishContent: '成功发布知识流水线后,此知识库的分段结构将无法修改。您确定要发布吗?',
|
||||
publishAsPipeline: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue