add multi options
This commit is contained in:
parent
7a13cda9a3
commit
db06f85c2a
|
|
@ -45,6 +45,66 @@ class UnstructuredFile_DocumentLoaders implements INode {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'http://localhost:8000/general/v0/general'
|
default: 'http://localhost:8000/general/v0/general'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Element Type',
|
||||||
|
name: 'elementType',
|
||||||
|
description:
|
||||||
|
'Unstructured partition document into different types, select the types to return. If not selected, all types will be returned',
|
||||||
|
type: 'multiOptions',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'FigureCaption',
|
||||||
|
name: 'FigureCaption'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'NarrativeText',
|
||||||
|
name: 'NarrativeText'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ListItem',
|
||||||
|
name: 'ListItem'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Title',
|
||||||
|
name: 'Title'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Address',
|
||||||
|
name: 'Address'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Table',
|
||||||
|
name: 'Table'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'PageBreak',
|
||||||
|
name: 'PageBreak'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Header',
|
||||||
|
name: 'Header'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Footer',
|
||||||
|
name: 'Footer'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'UncategorizedText',
|
||||||
|
name: 'UncategorizedText'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Image',
|
||||||
|
name: 'Image'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Formula',
|
||||||
|
name: 'Formula'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: [],
|
||||||
|
optional: true,
|
||||||
|
additionalParams: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Metadata',
|
label: 'Metadata',
|
||||||
name: 'metadata',
|
name: 'metadata',
|
||||||
|
|
@ -52,13 +112,13 @@ class UnstructuredFile_DocumentLoaders implements INode {
|
||||||
optional: true,
|
optional: true,
|
||||||
additionalParams: true
|
additionalParams: true
|
||||||
}
|
}
|
||||||
/*TODO Add Filter Options*/
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||||
const filePath = nodeData.inputs?.filePath as string
|
const filePath = nodeData.inputs?.filePath as string
|
||||||
const unstructuredAPIUrl = nodeData.inputs?.unstructuredAPIUrl as string
|
const unstructuredAPIUrl = nodeData.inputs?.unstructuredAPIUrl as string
|
||||||
|
const elementType = nodeData.inputs?.elementType as string
|
||||||
const metadata = nodeData.inputs?.metadata
|
const metadata = nodeData.inputs?.metadata
|
||||||
|
|
||||||
const obj: UnstructuredLoaderOptions = { apiUrl: unstructuredAPIUrl }
|
const obj: UnstructuredLoaderOptions = { apiUrl: unstructuredAPIUrl }
|
||||||
|
|
@ -70,6 +130,15 @@ class UnstructuredFile_DocumentLoaders implements INode {
|
||||||
const loader = new UnstructuredLoader(filePath, obj)
|
const loader = new UnstructuredLoader(filePath, obj)
|
||||||
const docs = await loader.load()
|
const docs = await loader.load()
|
||||||
|
|
||||||
|
let elementTypes: string[] = []
|
||||||
|
if (elementType) {
|
||||||
|
try {
|
||||||
|
elementTypes = JSON.parse(elementType)
|
||||||
|
} catch (e) {
|
||||||
|
elementTypes = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
|
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
|
||||||
let finaldocs = []
|
let finaldocs = []
|
||||||
|
|
@ -83,10 +152,10 @@ class UnstructuredFile_DocumentLoaders implements INode {
|
||||||
}
|
}
|
||||||
finaldocs.push(newdoc)
|
finaldocs.push(newdoc)
|
||||||
}
|
}
|
||||||
return finaldocs
|
return elementTypes.length ? finaldocs.filter((doc) => elementTypes.includes(doc.metadata.category)) : finaldocs
|
||||||
}
|
}
|
||||||
|
|
||||||
return docs
|
return elementTypes.length ? docs.filter((doc) => elementTypes.includes(doc.metadata.category)) : docs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,66 @@ class UnstructuredFolder_DocumentLoaders implements INode {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'http://localhost:8000/general/v0/general'
|
default: 'http://localhost:8000/general/v0/general'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Element Type',
|
||||||
|
name: 'elementType',
|
||||||
|
description:
|
||||||
|
'Unstructured partition document into different types, select the types to return. If not selected, all types will be returned',
|
||||||
|
type: 'multiOptions',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'FigureCaption',
|
||||||
|
name: 'FigureCaption'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'NarrativeText',
|
||||||
|
name: 'NarrativeText'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ListItem',
|
||||||
|
name: 'ListItem'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Title',
|
||||||
|
name: 'Title'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Address',
|
||||||
|
name: 'Address'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Table',
|
||||||
|
name: 'Table'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'PageBreak',
|
||||||
|
name: 'PageBreak'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Header',
|
||||||
|
name: 'Header'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Footer',
|
||||||
|
name: 'Footer'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'UncategorizedText',
|
||||||
|
name: 'UncategorizedText'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Image',
|
||||||
|
name: 'Image'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Formula',
|
||||||
|
name: 'Formula'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: [],
|
||||||
|
optional: true,
|
||||||
|
additionalParams: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Metadata',
|
label: 'Metadata',
|
||||||
name: 'metadata',
|
name: 'metadata',
|
||||||
|
|
@ -52,7 +112,6 @@ class UnstructuredFolder_DocumentLoaders implements INode {
|
||||||
optional: true,
|
optional: true,
|
||||||
additionalParams: true
|
additionalParams: true
|
||||||
}
|
}
|
||||||
/*TODO Add Filter Options*/
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,6 +119,7 @@ class UnstructuredFolder_DocumentLoaders implements INode {
|
||||||
const folderPath = nodeData.inputs?.folderPath as string
|
const folderPath = nodeData.inputs?.folderPath as string
|
||||||
const unstructuredAPIUrl = nodeData.inputs?.unstructuredAPIUrl as string
|
const unstructuredAPIUrl = nodeData.inputs?.unstructuredAPIUrl as string
|
||||||
const metadata = nodeData.inputs?.metadata
|
const metadata = nodeData.inputs?.metadata
|
||||||
|
const elementType = nodeData.inputs?.elementType as string
|
||||||
|
|
||||||
const obj: UnstructuredLoaderOptions = { apiUrl: unstructuredAPIUrl }
|
const obj: UnstructuredLoaderOptions = { apiUrl: unstructuredAPIUrl }
|
||||||
|
|
||||||
|
|
@ -70,6 +130,15 @@ class UnstructuredFolder_DocumentLoaders implements INode {
|
||||||
const loader = new UnstructuredDirectoryLoader(folderPath, obj)
|
const loader = new UnstructuredDirectoryLoader(folderPath, obj)
|
||||||
const docs = await loader.load()
|
const docs = await loader.load()
|
||||||
|
|
||||||
|
let elementTypes: string[] = []
|
||||||
|
if (elementType) {
|
||||||
|
try {
|
||||||
|
elementTypes = JSON.parse(elementType)
|
||||||
|
} catch (e) {
|
||||||
|
elementTypes = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
|
const parsedMetadata = typeof metadata === 'object' ? metadata : JSON.parse(metadata)
|
||||||
let finaldocs = []
|
let finaldocs = []
|
||||||
|
|
@ -83,10 +152,10 @@ class UnstructuredFolder_DocumentLoaders implements INode {
|
||||||
}
|
}
|
||||||
finaldocs.push(newdoc)
|
finaldocs.push(newdoc)
|
||||||
}
|
}
|
||||||
return finaldocs
|
return elementTypes.length ? finaldocs.filter((doc) => elementTypes.includes(doc.metadata.category)) : finaldocs
|
||||||
}
|
}
|
||||||
|
|
||||||
return docs
|
return elementTypes.length ? docs.filter((doc) => elementTypes.includes(doc.metadata.category)) : docs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class ElasicsearchExisting_VectorStores extends ElasticSearchBase implements INo
|
||||||
async constructVectorStore(
|
async constructVectorStore(
|
||||||
embeddings: Embeddings,
|
embeddings: Embeddings,
|
||||||
elasticSearchClientArgs: ElasticClientArgs,
|
elasticSearchClientArgs: ElasticClientArgs,
|
||||||
docs: Document<Record<string, any>>[] | undefined
|
_: Document<Record<string, any>>[] | undefined
|
||||||
): Promise<VectorStore> {
|
): Promise<VectorStore> {
|
||||||
return await ElasticVectorSearch.fromExistingIndex(embeddings, elasticSearchClientArgs)
|
return await ElasticVectorSearch.fromExistingIndex(embeddings, elasticSearchClientArgs)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
export type NodeParamsType =
|
export type NodeParamsType =
|
||||||
| 'asyncOptions'
|
| 'asyncOptions'
|
||||||
| 'options'
|
| 'options'
|
||||||
|
| 'multiOptions'
|
||||||
| 'string'
|
| 'string'
|
||||||
| 'number'
|
| 'number'
|
||||||
| 'boolean'
|
| 'boolean'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
|
import { Popper, FormControl, TextField, Box, Typography } from '@mui/material'
|
||||||
|
import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete'
|
||||||
|
import { styled } from '@mui/material/styles'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
const StyledPopper = styled(Popper)({
|
||||||
|
boxShadow: '0px 8px 10px -5px rgb(0 0 0 / 20%), 0px 16px 24px 2px rgb(0 0 0 / 14%), 0px 6px 30px 5px rgb(0 0 0 / 12%)',
|
||||||
|
borderRadius: '10px',
|
||||||
|
[`& .${autocompleteClasses.listbox}`]: {
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
'& ul': {
|
||||||
|
padding: 10,
|
||||||
|
margin: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const MultiDropdown = ({ name, value, options, onSelect, disabled = false, disableClearable = false }) => {
|
||||||
|
const customization = useSelector((state) => state.customization)
|
||||||
|
const findMatchingOptions = (options = [], internalValue) => {
|
||||||
|
let values = []
|
||||||
|
if (internalValue && typeof internalValue === 'string') values = JSON.parse(internalValue)
|
||||||
|
else values = internalValue
|
||||||
|
return options.filter((option) => values.includes(option.name))
|
||||||
|
}
|
||||||
|
const getDefaultOptionValue = () => []
|
||||||
|
let [internalValue, setInternalValue] = useState(value ?? [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl sx={{ mt: 1, width: '100%' }} size='small'>
|
||||||
|
<Autocomplete
|
||||||
|
id={name}
|
||||||
|
disabled={disabled}
|
||||||
|
disableClearable={disableClearable}
|
||||||
|
size='small'
|
||||||
|
multiple
|
||||||
|
filterSelectedOptions
|
||||||
|
options={options || []}
|
||||||
|
value={findMatchingOptions(options, internalValue) || getDefaultOptionValue()}
|
||||||
|
onChange={(e, selections) => {
|
||||||
|
let value = ''
|
||||||
|
if (selections.length) {
|
||||||
|
const selectionNames = []
|
||||||
|
for (let i = 0; i < selections.length; i += 1) {
|
||||||
|
selectionNames.push(selections[i].name)
|
||||||
|
}
|
||||||
|
value = JSON.stringify(selectionNames)
|
||||||
|
}
|
||||||
|
setInternalValue(value)
|
||||||
|
onSelect(value)
|
||||||
|
}}
|
||||||
|
PopperComponent={StyledPopper}
|
||||||
|
renderInput={(params) => <TextField {...params} value={internalValue} />}
|
||||||
|
renderOption={(props, option) => (
|
||||||
|
<Box component='li' {...props}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<Typography variant='h5'>{option.label}</Typography>
|
||||||
|
{option.description && (
|
||||||
|
<Typography sx={{ color: customization.isDarkMode ? '#9e9e9e' : '' }}>{option.description}</Typography>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiDropdown.propTypes = {
|
||||||
|
name: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
options: PropTypes.array,
|
||||||
|
onSelect: PropTypes.func,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
disableClearable: PropTypes.bool
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,20 @@ export const initNode = (nodeData, newNodeId) => {
|
||||||
const incoming = nodeData.inputs ? nodeData.inputs.length : 0
|
const incoming = nodeData.inputs ? nodeData.inputs.length : 0
|
||||||
const outgoing = 1
|
const outgoing = 1
|
||||||
|
|
||||||
const whitelistTypes = ['asyncOptions', 'options', 'string', 'number', 'boolean', 'password', 'json', 'code', 'date', 'file', 'folder']
|
const whitelistTypes = [
|
||||||
|
'asyncOptions',
|
||||||
|
'options',
|
||||||
|
'multiOptions',
|
||||||
|
'string',
|
||||||
|
'number',
|
||||||
|
'boolean',
|
||||||
|
'password',
|
||||||
|
'json',
|
||||||
|
'code',
|
||||||
|
'date',
|
||||||
|
'file',
|
||||||
|
'folder'
|
||||||
|
]
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
for (let i = 0; i < incoming; i += 1) {
|
for (let i = 0; i < incoming; i += 1) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { IconArrowsMaximize, IconEdit, IconAlertTriangle } from '@tabler/icons'
|
||||||
|
|
||||||
// project import
|
// project import
|
||||||
import { Dropdown } from 'ui-component/dropdown/Dropdown'
|
import { Dropdown } from 'ui-component/dropdown/Dropdown'
|
||||||
|
import { MultiDropdown } from 'ui-component/dropdown/MultiDropdown'
|
||||||
import { AsyncDropdown } from 'ui-component/dropdown/AsyncDropdown'
|
import { AsyncDropdown } from 'ui-component/dropdown/AsyncDropdown'
|
||||||
import { Input } from 'ui-component/input/Input'
|
import { Input } from 'ui-component/input/Input'
|
||||||
import { File } from 'ui-component/file/File'
|
import { File } from 'ui-component/file/File'
|
||||||
|
|
@ -308,6 +309,15 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
|
||||||
value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
|
value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{inputParam.type === 'multiOptions' && (
|
||||||
|
<MultiDropdown
|
||||||
|
disabled={disabled}
|
||||||
|
name={inputParam.name}
|
||||||
|
options={inputParam.options}
|
||||||
|
onSelect={(newValue) => (data.inputs[inputParam.name] = newValue)}
|
||||||
|
value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{inputParam.type === 'asyncOptions' && (
|
{inputParam.type === 'asyncOptions' && (
|
||||||
<>
|
<>
|
||||||
{data.inputParams.length === 1 && <div style={{ marginTop: 10 }} />}
|
{data.inputParams.length === 1 && <div style={{ marginTop: 10 }} />}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue