feat: Implement data source store with slices for local files, online documents, website crawls, and online drives

feat/rag-pipeline
twwu 7 months ago
parent ddde576b4a
commit 2dd1f41ad3

@ -0,0 +1,34 @@
import { useContext } from 'react'
import { createStore, useStore } from 'zustand'
import { DataSourceContext } from './provider'
import type { LocalFileSliceShape } from './slices/local-file'
import { createLocalFileSlice } from './slices/local-file'
import type { OnlineDocumentSliceShape } from './slices/online-document'
import { createOnlineDocumentSlice } from './slices/online-document'
import type { WebsiteCrawlSliceShape } from './slices/website-crawl'
import { createWebsiteCrawlSlice } from './slices/website-crawl'
import type { OnlineDriveSliceShape } from './slices/online-drive'
import { createOnlineDriveSlice } from './slices/online-drive'
export type DataSourceShape =
LocalFileSliceShape &
OnlineDocumentSliceShape &
WebsiteCrawlSliceShape &
OnlineDriveSliceShape
export const createDataSourceStore = () => {
return createStore<DataSourceShape>((...args) => ({
...createLocalFileSlice(...args),
...createOnlineDocumentSlice(...args),
...createWebsiteCrawlSlice(...args),
...createOnlineDriveSlice(...args),
}))
}
export const useDataSourceStore = <T>(selector: (state: DataSourceShape) => T): T => {
const store = useContext(DataSourceContext)
if (!store)
throw new Error('Missing DataSourceContext.Provider in the tree')
return useStore(store, selector)
}

@ -0,0 +1,29 @@
import { createContext, useRef } from 'react'
import { createDataSourceStore } from './'
type DataSourceStoreApi = ReturnType<typeof createDataSourceStore>
type DataSourceContextType = DataSourceStoreApi | null
export const DataSourceContext = createContext<DataSourceContextType>(null)
type DataSourceProviderProps = {
children: React.ReactNode
}
const DataSourceProvider = ({
children,
}: DataSourceProviderProps) => {
const storeRef = useRef<DataSourceStoreApi>()
if (!storeRef.current)
storeRef.current = createDataSourceStore()
return (
<DataSourceContext.Provider value={storeRef.current!}>
{children}
</DataSourceContext.Provider>
)
}
export default DataSourceProvider

@ -0,0 +1,22 @@
import type { StateCreator } from 'zustand'
import type { FileItem } from '@/models/datasets'
export type LocalFileSliceShape = {
localFileList: FileItem[]
setLocalFileList: (fileList: FileItem[]) => void
currentLocalFile: File | undefined
setCurrentLocalFile: (file: File | undefined) => void
}
export const createLocalFileSlice: StateCreator<LocalFileSliceShape> = (set) => {
return ({
localFileList: [],
setLocalFileList: (fileList: FileItem[]) => set(() => ({
localFileList: fileList,
})),
currentLocalFile: undefined,
setCurrentLocalFile: (file: File | undefined) => set(() => ({
currentLocalFile: file,
})),
})
}

@ -0,0 +1,46 @@
import type { StateCreator } from 'zustand'
import type { DataSourceNotionWorkspace, NotionPage } from '@/models/common'
export type OnlineDocumentSliceShape = {
documentData: DataSourceNotionWorkspace[]
setDocumentData: (documentData: DataSourceNotionWorkspace[]) => void
searchValue: string
setSearchValue: (searchValue: string) => void
currentWorkspaceId: string
setCurrentWorkspaceId: (workspaceId: string) => void
onlineDocuments: NotionPage[]
setOnlineDocuments: (documents: NotionPage[]) => void
currentDocument: NotionPage | undefined
setCurrentDocument: (document: NotionPage | undefined) => void
selectedPagesId: Set<string>
setSelectedPagesId: (selectedPagesId: Set<string>) => void
}
export const createOnlineDocumentSlice: StateCreator<OnlineDocumentSliceShape> = (set, get) => {
return ({
documentData: [],
setDocumentData: (documentData: DataSourceNotionWorkspace[]) => set(() => ({
documentData,
})),
searchValue: '',
setSearchValue: (searchValue: string) => set(() => ({
searchValue,
})),
currentWorkspaceId: '',
setCurrentWorkspaceId: (workspaceId: string) => set(() => ({
currentWorkspaceId: workspaceId,
})),
onlineDocuments: [],
setOnlineDocuments: (documents: NotionPage[]) => set(() => ({
onlineDocuments: documents,
})),
currentDocument: undefined,
setCurrentDocument: (document: NotionPage | undefined) => set(() => ({
currentDocument: document,
})),
selectedPagesId: new Set([...get().onlineDocuments.map(doc => doc.page_id)]),
setSelectedPagesId: (selectedPagesId: Set<string>) => set(() => ({
selectedPagesId,
})),
})
}

@ -0,0 +1,44 @@
import type { StateCreator } from 'zustand'
import { type OnlineDriveFile, OnlineDriveFileType } from '@/models/pipeline'
export type OnlineDriveSliceShape = {
prefix: string[]
setPrefix: (prefix: string[]) => void
keywords: string
setKeywords: (keywords: string) => void
startAfter: string
setStartAfter: (startAfter: string) => void
selectedFileList: string[]
setSelectedFileList: (selectedFileList: string[]) => void
fileList: OnlineDriveFile[]
setFileList: (fileList: OnlineDriveFile[]) => void
}
export const createOnlineDriveSlice: StateCreator<OnlineDriveSliceShape> = (set) => {
return ({
prefix: [],
setPrefix: (prefix: string[]) => set(() => ({
prefix,
})),
keywords: '',
setKeywords: (keywords: string) => set(() => ({
keywords,
})),
startAfter: '',
setStartAfter: (startAfter: string) => set(() => ({
startAfter,
})),
selectedFileList: [],
setSelectedFileList: (selectedFileList: string[]) => set(() => ({
selectedFileList,
})),
fileList: [{
key: 'Bucket_1',
size: 1024, // unit bytes
type: OnlineDriveFileType.bucket,
}],
setFileList: (fileList: OnlineDriveFile[]) => set(() => ({
fileList,
})),
})
}

@ -0,0 +1,41 @@
import type { StateCreator } from 'zustand'
import type { CrawlResult, CrawlResultItem } from '@/models/datasets'
import { CrawlStep } from '@/models/datasets'
export type WebsiteCrawlSliceShape = {
websitePages: CrawlResultItem[]
setWebsitePages: (pages: CrawlResultItem[]) => void
currentWebsite: CrawlResultItem | undefined
setCurrentWebsite: (website: CrawlResultItem | undefined) => void
crawlResult: CrawlResult | undefined
setCrawlResult: (result: CrawlResult | undefined) => void
step: CrawlStep
setStep: (step: CrawlStep) => void
previewIndex: number
setPreviewIndex: (index: number) => void
}
export const createWebsiteCrawlSlice: StateCreator<WebsiteCrawlSliceShape> = (set) => {
return ({
websitePages: [],
setWebsitePages: (pages: CrawlResultItem[]) => set(() => ({
websitePages: pages,
})),
currentWebsite: undefined,
setCurrentWebsite: (website: CrawlResultItem | undefined) => set(() => ({
currentWebsite: website,
})),
crawlResult: undefined,
setCrawlResult: (result: CrawlResult | undefined) => set(() => ({
crawlResult: result,
})),
step: CrawlStep.init,
setStep: (step: CrawlStep) => set(() => ({
step,
})),
previewIndex: -1,
setPreviewIndex: (index: number) => set(() => ({
previewIndex: index,
})),
})
}

@ -28,6 +28,7 @@ import type { InitialDocumentDetail, PublishedPipelineRunPreviewResponse, Publis
import { DatasourceType } from '@/models/pipeline'
import { TransferMethod } from '@/types/app'
import { useAddDocumentsSteps, useLocalFile, useOnlineDocuments, useOnlineDrive, useWebsiteCrawl } from './hooks'
import DataSourceProvider from './data-source/store/provider'
const CreateFormPipeline = () => {
const { t } = useTranslation()
@ -399,4 +400,12 @@ const CreateFormPipeline = () => {
)
}
export default CreateFormPipeline
const CreateFormPipelineWrapper = () => {
return (
<DataSourceProvider>
<CreateFormPipeline />
</DataSourceProvider>
)
}
export default CreateFormPipelineWrapper

@ -15,6 +15,7 @@ import { TransferMethod } from '@/types/app'
import CloseButton from './close-button'
import Header from './header'
import FooterTips from './footer-tips'
import DataSourceProvider from '@/app/components/datasets/documents/create-from-pipeline/data-source/store/provider'
const TestRunPanel = () => {
const setShowDebugAndPreviewPanel = useWorkflowStoreWithSelector(state => state.setShowDebugAndPreviewPanel)
@ -209,4 +210,12 @@ const TestRunPanel = () => {
)
}
export default TestRunPanel
const TestRunPanelWrapper = () => {
return (
<DataSourceProvider>
<TestRunPanel />
</DataSourceProvider>
)
}
export default TestRunPanelWrapper

@ -10,8 +10,9 @@ const translation = {
description: 'Import from a DSL file',
},
createKnowledge: 'Create Knowledge',
errorTip: 'Failed to create a Knowledge Pipeline',
successTip: 'Successfully created a Knowledge Pipeline',
errorTip: 'Failed to create a Knowledge Base',
successTip: 'Successfully created a Knowledge Base',
caution: 'Caution',
},
tabs: {
builtInPipeline: 'Built-in pipeline',

@ -1,20 +1,21 @@
const translation = {
creation: {
title: '创建知识库流水线',
title: '创建知识库 pipeline',
createFromScratch: {
title: '从零开始创建',
description: '空白知识库流水线',
description: '空白知识库 pipeline',
},
ImportDSL: {
title: '导入',
description: '从 DSL 文件导入',
},
createKnowledge: '创建知识库',
errorTip: '创建知识库流水线失败',
successTip: '成功创建知识库流水线',
errorTip: '创建知识库',
successTip: '成功创建知识库',
caution: '注意',
},
tabs: {
builtInPipeline: '内置流水线',
builtInPipeline: '内置 pipeline',
customized: '自定义',
},
operations: {
@ -22,7 +23,7 @@ const translation = {
details: '详情',
editInfo: '编辑信息',
exportDSL: '导出 DSL',
useTemplate: '使用此知识库流水线',
useTemplate: '使用此知识库 pipeline',
backToDataSource: '返回数据源',
process: '处理',
dataSource: '数据源',
@ -34,15 +35,15 @@ const translation = {
knowledgeDescription: '知识库描述',
knowledgeDescriptionPlaceholder: '描述知识库中的内容。详细的描述可以让 AI 更准确地访问数据集的内容。如果为空Dify 将使用默认的命中策略。(可选)',
knowledgePermissions: '权限',
editPipelineInfo: '编辑流水线信息',
pipelineNameAndIcon: '流水线名称和图标',
editPipelineInfo: '编辑 pipeline 信息',
pipelineNameAndIcon: 'pipeline 名称和图标',
deletePipeline: {
title: '要删除此流水线模板吗?',
content: '删除流水线模板是不可逆的。',
title: '要删除此 pipeline 模板吗?',
content: '删除 pipeline 模板是不可逆的。',
},
exportDSL: {
successTip: '成功导出流水线 DSL',
errorTip: '导出流水线 DSL 失败',
successTip: '成功导出 pipeline DSL',
errorTip: '导出 pipeline DSL 失败',
},
details: {
createdBy: '由 {{author}} 创建',
@ -67,7 +68,7 @@ const translation = {
inputField: '输入字段',
inputFieldPanel: {
title: '用户输入字段',
description: '用户输入字段用于定义和收集流水线执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。',
description: '用户输入字段用于定义和收集 pipeline 执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。',
uniqueInputs: {
title: '非共享输入',
tooltip: '非共享输入只能被选定的数据源及其下游节点访问。用户在选择其他数据源时不需要填写它。只有数据源变量引用的输入字段才会出现在第一步数据源中。所有其他字段将在第二步Process Documents中显示。',

Loading…
Cancel
Save