Chore/update deprecating nodes (#2540)

* update deprecating nodes

* add filters use cases to marketplace

* update log level
This commit is contained in:
Henry Heng
2024-07-12 18:37:57 +01:00
committed by GitHub
parent 9ea439d135
commit 363d1bfc44
144 changed files with 6939 additions and 12160 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@@ -14,6 +14,7 @@ import {
TableHead,
TableRow,
Typography,
Stack,
useTheme
} from '@mui/material'
@@ -42,6 +43,7 @@ export const MarketplaceTable = ({
filterByBadge,
filterByType,
filterByFramework,
filterByUsecases,
goToCanvas,
goToTool,
isLoading
@@ -68,19 +70,21 @@ export const MarketplaceTable = ({
}}
>
<TableRow>
<StyledTableCell component='th' scope='row' style={{ width: '15%' }} key='0'>
<StyledTableCell sx={{ minWidth: '150px' }} component='th' scope='row' key='0'>
Name
</StyledTableCell>
<StyledTableCell component='th' scope='row' style={{ width: '5%' }} key='1'>
<StyledTableCell sx={{ minWidth: '100px' }} component='th' scope='row' key='1'>
Type
</StyledTableCell>
<StyledTableCell style={{ width: '35%' }} key='2'>
Description
<StyledTableCell key='2'>Description</StyledTableCell>
<StyledTableCell sx={{ minWidth: '100px' }} key='3'>
Framework
</StyledTableCell>
<StyledTableCell style={{ width: '35%' }} key='3'>
Nodes
<StyledTableCell sx={{ minWidth: '100px' }} key='4'>
Use cases
</StyledTableCell>
<StyledTableCell component='th' scope='row' style={{ width: '5%' }} key='4'>
<StyledTableCell key='5'>Nodes</StyledTableCell>
<StyledTableCell component='th' scope='row' key='6'>
&nbsp;
</StyledTableCell>
</TableRow>
@@ -104,6 +108,12 @@ export const MarketplaceTable = ({
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
</StyledTableRow>
<StyledTableRow>
<StyledTableCell>
@@ -121,6 +131,12 @@ export const MarketplaceTable = ({
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
<StyledTableCell>
<Skeleton variant='text' />
</StyledTableCell>
</StyledTableRow>
</>
) : (
@@ -130,6 +146,7 @@ export const MarketplaceTable = ({
.filter(filterByType)
.filter(filterFunction)
.filter(filterByFramework)
.filter(filterByUsecases)
.map((row, index) => (
<StyledTableRow key={index}>
<StyledTableCell key='0'>
@@ -158,29 +175,50 @@ export const MarketplaceTable = ({
</Typography>
</StyledTableCell>
<StyledTableCell key='3'>
<div
style={{
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 5
}}
>
{row.categories &&
row.categories
.split(',')
.map((tag, index) => (
<Chip
variant='outlined'
key={index}
size='small'
label={tag.toUpperCase()}
style={{ marginRight: 3, marginBottom: 3 }}
/>
))}
</div>
<Stack flexDirection='row' sx={{ gap: 1, flexWrap: 'wrap' }}>
{row.framework &&
row.framework.length > 0 &&
row.framework.map((framework, index) => (
<Chip
variant='outlined'
key={index}
size='small'
label={framework}
style={{ marginRight: 3, marginBottom: 3 }}
/>
))}
</Stack>
</StyledTableCell>
<StyledTableCell key='4'>
<Stack flexDirection='row' sx={{ gap: 1, flexWrap: 'wrap' }}>
{row.usecases &&
row.usecases.length > 0 &&
row.usecases.map((usecase, index) => (
<Chip
variant='outlined'
key={index}
size='small'
label={usecase}
style={{ marginRight: 3, marginBottom: 3 }}
/>
))}
</Stack>
</StyledTableCell>
<StyledTableCell key='5'>
<Stack flexDirection='row' sx={{ gap: 1, flexWrap: 'wrap' }}>
{row.categories &&
row.categories.map((tag, index) => (
<Chip
variant='outlined'
key={index}
size='small'
label={tag}
style={{ marginRight: 3, marginBottom: 3 }}
/>
))}
</Stack>
</StyledTableCell>
<StyledTableCell key='6'>
<Typography>
{row.badge &&
row.badge
@@ -213,6 +251,7 @@ MarketplaceTable.propTypes = {
filterByBadge: PropTypes.func,
filterByType: PropTypes.func,
filterByFramework: PropTypes.func,
filterByUsecases: PropTypes.func,
goToTool: PropTypes.func,
goToCanvas: PropTypes.func,
isLoading: PropTypes.bool
+134 -171
View File
@@ -40,6 +40,7 @@ import { StyledFab } from '@/ui-component/button/StyledFab'
import { IconPlus, IconSearch, IconMinus, IconX } from '@tabler/icons-react'
import LlamaindexPNG from '@/assets/images/llamaindex.png'
import LangChainPNG from '@/assets/images/langchain.png'
import utilNodesPNG from '@/assets/images/utilNodes.png'
// const
import { baseURL } from '@/store/constant'
@@ -71,28 +72,6 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
const prevOpen = useRef(open)
const ps = useRef()
// Temporary method to handle Deprecating Vector Store and New ones
const categorizeVectorStores = (nodes, accordianCategories, isFilter) => {
const obj = { ...nodes }
const vsNodes = obj['Vector Stores'] ?? []
const deprecatingNodes = []
const newNodes = []
for (const vsNode of vsNodes) {
if (vsNode.badge === 'DEPRECATING') deprecatingNodes.push(vsNode)
else newNodes.push(vsNode)
}
delete obj['Vector Stores']
if (deprecatingNodes.length) {
obj['Vector Stores;DEPRECATING'] = deprecatingNodes
accordianCategories['Vector Stores;DEPRECATING'] = isFilter ? true : false
}
if (newNodes.length) {
obj['Vector Stores;NEW'] = newNodes
accordianCategories['Vector Stores;NEW'] = isFilter ? true : false
}
setNodes(obj)
}
const scrollTop = () => {
const curr = ps.current
if (curr) {
@@ -141,10 +120,13 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
const groupByTags = (nodes, newTabValue = 0) => {
const langchainNodes = nodes.filter((nd) => !nd.tags)
const llmaindexNodes = nodes.filter((nd) => nd.tags && nd.tags.includes('LlamaIndex'))
const utilitiesNodes = nodes.filter((nd) => nd.tags && nd.tags.includes('Utilities'))
if (newTabValue === 0) {
return langchainNodes
} else {
} else if (newTabValue === 1) {
return llmaindexNodes
} else {
return utilitiesNodes
}
}
@@ -176,7 +158,6 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
}
}
setNodes(filteredResult)
categorizeVectorStores(filteredResult, accordianCategories, isFilter)
accordianCategories['Multi Agents'] = true
setCategoryExpanded(accordianCategories)
} else {
@@ -197,7 +178,6 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
filteredResult[category] = result[category]
}
setNodes(filteredResult)
categorizeVectorStores(filteredResult, accordianCategories, isFilter)
setCategoryExpanded(accordianCategories)
}
}
@@ -224,6 +204,16 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
event.dataTransfer.effectAllowed = 'move'
}
const getImage = (tabValue) => {
if (tabValue === 0) {
return LangChainPNG
} else if (tabValue === 1) {
return LlamaindexPNG
} else {
return utilNodesPNG
}
}
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus()
@@ -332,7 +322,7 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
onChange={handleTabChange}
aria-label='tabs'
>
{['LangChain', 'LlamaIndex'].map((item, index) => (
{['LangChain', 'LlamaIndex', 'Utilities'].map((item, index) => (
<Tab
icon={
<div
@@ -342,12 +332,12 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
>
<img
style={{
width: '25px',
height: '25px',
width: '20px',
height: '20px',
borderRadius: '50%',
objectFit: 'contain'
}}
src={index === 0 ? LangChainPNG : LlamaindexPNG}
src={getImage(index)}
alt={item}
/>
</div>
@@ -359,27 +349,6 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
{...a11yProps(index)}
></Tab>
))}
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
borderRadius: 10,
background: 'rgb(254,252,191)',
paddingLeft: 6,
paddingRight: 6,
paddingTop: 1,
paddingBottom: 1,
width: 'max-content',
position: 'absolute',
top: 0,
right: 0,
fontSize: '0.65rem',
fontWeight: 700
}}
>
<span style={{ color: 'rgb(116,66,16)' }}>BETA</span>
</div>
</Tabs>
)}
@@ -418,135 +387,129 @@ const AddNodes = ({ nodesData, node, isAgentCanvas }) => {
>
{Object.keys(nodes)
.sort()
.map((category) =>
category === 'Vector Stores' ? (
<></>
) : (
<Accordion
expanded={categoryExpanded[category] || false}
onChange={handleAccordionChange(category)}
key={category}
disableGutters
.map((category) => (
<Accordion
expanded={categoryExpanded[category] || false}
onChange={handleAccordionChange(category)}
key={category}
disableGutters
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls={`nodes-accordian-${category}`}
id={`nodes-accordian-header-${category}`}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls={`nodes-accordian-${category}`}
id={`nodes-accordian-header-${category}`}
>
{category.split(';').length > 1 ? (
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
{category.split(';').length > 1 ? (
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
}}
>
<Typography variant='h5'>{category.split(';')[0]}</Typography>
&nbsp;
<Chip
sx={{
width: 'max-content',
fontWeight: 700,
fontSize: '0.65rem',
background:
category.split(';')[1] === 'DEPRECATING'
? theme.palette.warning.main
: theme.palette.teal.main,
color:
category.split(';')[1] !== 'DEPRECATING'
? 'white'
: 'inherit'
}}
size='small'
label={category.split(';')[1]}
/>
</div>
) : (
<Typography variant='h5'>{category}</Typography>
)}
</AccordionSummary>
<AccordionDetails>
{nodes[category].map((node, index) => (
<div
key={node.name}
onDragStart={(event) => onDragStart(event, node)}
draggable
>
<ListItemButton
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
cursor: 'move'
}}
>
<Typography variant='h5'>{category.split(';')[0]}</Typography>
&nbsp;
<Chip
sx={{
width: 'max-content',
fontWeight: 700,
fontSize: '0.65rem',
background:
category.split(';')[1] === 'DEPRECATING'
? theme.palette.warning.main
: theme.palette.teal.main,
color:
category.split(';')[1] !== 'DEPRECATING'
? 'white'
: 'inherit'
}}
size='small'
label={category.split(';')[1]}
/>
</div>
) : (
<Typography variant='h5'>{category}</Typography>
)}
</AccordionSummary>
<AccordionDetails>
{nodes[category].map((node, index) => (
<div
key={node.name}
onDragStart={(event) => onDragStart(event, node)}
draggable
>
<ListItemButton
sx={{
p: 0,
borderRadius: `${customization.borderRadius}px`,
cursor: 'move'
}}
>
<ListItem alignItems='center'>
<ListItemAvatar>
<ListItem alignItems='center'>
<ListItemAvatar>
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt={node.name}
src={`${baseURL}/api/v1/node-icon/${node.name}`}
/>
</div>
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary={
<div
style={{
width: 50,
height: 50,
borderRadius: '50%',
backgroundColor: 'white'
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 10,
objectFit: 'contain'
}}
alt={node.name}
src={`${baseURL}/api/v1/node-icon/${node.name}`}
/>
<span>{node.label}</span>
&nbsp;
{node.badge && (
<Chip
sx={{
width: 'max-content',
fontWeight: 700,
fontSize: '0.65rem',
background:
node.badge === 'DEPRECATING'
? theme.palette.warning.main
: theme.palette.teal.main,
color:
node.badge !== 'DEPRECATING'
? 'white'
: 'inherit'
}}
size='small'
label={node.badge}
/>
)}
</div>
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary={
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
}}
>
<span>{node.label}</span>
&nbsp;
{node.badge && (
<Chip
sx={{
width: 'max-content',
fontWeight: 700,
fontSize: '0.65rem',
background:
node.badge === 'DEPRECATING'
? theme.palette.warning
.main
: theme.palette.teal
.main,
color:
node.badge !== 'DEPRECATING'
? 'white'
: 'inherit'
}}
size='small'
label={node.badge}
/>
)}
</div>
}
secondary={node.description}
/>
</ListItem>
</ListItemButton>
{index === nodes[category].length - 1 ? null : <Divider />}
</div>
))}
</AccordionDetails>
</Accordion>
)
)}
}
secondary={node.description}
/>
</ListItem>
</ListItemButton>
{index === nodes[category].length - 1 ? null : <Divider />}
</div>
))}
</AccordionDetails>
</Accordion>
))}
</List>
</Box>
</PerfectScrollbar>
+95 -12
View File
@@ -15,17 +15,23 @@ import {
OutlinedInput,
Checkbox,
ListItemText,
Skeleton
Skeleton,
FormControlLabel,
ToggleButtonGroup,
MenuItem,
Button
} from '@mui/material'
import { useTheme } from '@mui/material/styles'
import { IconLayoutGrid, IconList } from '@tabler/icons-react'
import { IconLayoutGrid, IconList, IconX } from '@tabler/icons-react'
// project imports
import MainCard from '@/ui-component/cards/MainCard'
import ItemCard from '@/ui-component/cards/ItemCard'
import { gridSpacing } from '@/store/constant'
import WorkflowEmptySVG from '@/assets/images/workflow_empty.svg'
import ToolDialog from '@/views/tools/ToolDialog'
import { MarketplaceTable } from '@/ui-component/table/MarketplaceTable'
import ViewHeader from '@/layout/MainLayout/ViewHeader'
import ErrorBoundary from '@/ErrorBoundary'
// API
import marketplacesApi from '@/api/marketplaces'
@@ -35,11 +41,7 @@ import useApi from '@/hooks/useApi'
// const
import { baseURL } from '@/store/constant'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import { MarketplaceTable } from '@/ui-component/table/MarketplaceTable'
import MenuItem from '@mui/material/MenuItem'
import ViewHeader from '@/layout/MainLayout/ViewHeader'
import ErrorBoundary from '@/ErrorBoundary'
import { gridSpacing } from '@/store/constant'
function TabPanel(props) {
const { children, value, index, ...other } = props
@@ -87,6 +89,9 @@ const Marketplace = () => {
const [isLoading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [images, setImages] = useState({})
const [usecases, setUsecases] = useState([])
const [eligibleUsecases, setEligibleUsecases] = useState([])
const [selectedUsecases, setSelectedUsecases] = useState([])
const [showToolDialog, setShowToolDialog] = useState(false)
const [toolDialogProps, setToolDialogProps] = useState({})
@@ -95,10 +100,14 @@ const Marketplace = () => {
const [view, setView] = React.useState(localStorage.getItem('mpDisplayStyle') || 'card')
const [search, setSearch] = useState('')
const [badgeFilter, setBadgeFilter] = useState([])
const [typeFilter, setTypeFilter] = useState([])
const [frameworkFilter, setFrameworkFilter] = useState([])
const clearAllUsecases = () => {
setSelectedUsecases([])
}
const handleBadgeFilterChange = (event) => {
const {
target: { value }
@@ -107,7 +116,9 @@ const Marketplace = () => {
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value
)
getEligibleUsecases({ typeFilter, badgeFilter: typeof value === 'string' ? value.split(',') : value, frameworkFilter, search })
}
const handleTypeFilterChange = (event) => {
const {
target: { value }
@@ -116,7 +127,9 @@ const Marketplace = () => {
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value
)
getEligibleUsecases({ typeFilter: typeof value === 'string' ? value.split(',') : value, badgeFilter, frameworkFilter, search })
}
const handleFrameworkFilterChange = (event) => {
const {
target: { value }
@@ -125,6 +138,7 @@ const Marketplace = () => {
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value
)
getEligibleUsecases({ typeFilter, badgeFilter, frameworkFilter: typeof value === 'string' ? value.split(',') : value, search })
}
const handleViewChange = (event, nextView) => {
@@ -135,11 +149,12 @@ const Marketplace = () => {
const onSearchChange = (event) => {
setSearch(event.target.value)
getEligibleUsecases({ typeFilter, badgeFilter, frameworkFilter, search: event.target.value })
}
function filterFlows(data) {
return (
data.categories?.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
(data.categories ? data.categories.join(',') : '').toLowerCase().indexOf(search.toLowerCase()) > -1 ||
data.templateName.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
(data.description && data.description.toLowerCase().indexOf(search.toLowerCase()) > -1)
)
@@ -154,7 +169,37 @@ const Marketplace = () => {
}
function filterByFramework(data) {
return frameworkFilter.length > 0 ? frameworkFilter.includes(data.framework) : true
return frameworkFilter.length > 0 ? (data.framework || []).some((item) => frameworkFilter.includes(item)) : true
}
function filterByUsecases(data) {
return selectedUsecases.length > 0 ? (data.usecases || []).some((item) => selectedUsecases.includes(item)) : true
}
const getEligibleUsecases = (filter) => {
if (!getAllTemplatesMarketplacesApi.data) return
let filteredData = getAllTemplatesMarketplacesApi.data
if (filter.badgeFilter.length > 0) filteredData = filteredData.filter((data) => filter.badgeFilter.includes(data.badge))
if (filter.typeFilter.length > 0) filteredData = filteredData.filter((data) => filter.typeFilter.includes(data.type))
if (filter.frameworkFilter.length > 0)
filteredData = filteredData.filter((data) => (data.framework || []).some((item) => filter.frameworkFilter.includes(item)))
if (filter.search) {
filteredData = filteredData.filter(
(data) =>
(data.categories ? data.categories.join(',') : '').toLowerCase().indexOf(filter.search.toLowerCase()) > -1 ||
data.templateName.toLowerCase().indexOf(filter.search.toLowerCase()) > -1 ||
(data.description && data.description.toLowerCase().indexOf(filter.search.toLowerCase()) > -1)
)
}
const usecases = []
for (let i = 0; i < filteredData.length; i += 1) {
if (filteredData[i].flowData) {
usecases.push(...filteredData[i].usecases)
}
}
setEligibleUsecases(Array.from(new Set(usecases)).sort())
}
const onUseTemplate = (selectedTool) => {
@@ -197,12 +242,13 @@ const Marketplace = () => {
if (getAllTemplatesMarketplacesApi.data) {
try {
const flows = getAllTemplatesMarketplacesApi.data
const usecases = []
const images = {}
for (let i = 0; i < flows.length; i += 1) {
if (flows[i].flowData) {
const flowDataStr = flows[i].flowData
const flowData = JSON.parse(flowDataStr)
usecases.push(...flows[i].usecases)
const nodes = flowData.nodes || []
images[flows[i].id] = []
for (let j = 0; j < nodes.length; j += 1) {
@@ -214,6 +260,8 @@ const Marketplace = () => {
}
}
setImages(images)
setUsecases(Array.from(new Set(usecases)).sort())
setEligibleUsecases(Array.from(new Set(usecases)).sort())
} catch (e) {
console.error(e)
}
@@ -384,6 +432,39 @@ const Marketplace = () => {
</ToggleButton>
</ToggleButtonGroup>
</ViewHeader>
<Stack direction='row' sx={{ gap: 2, alignItems: 'center', flexWrap: 'wrap' }}>
{usecases.map((usecase, index) => (
<FormControlLabel
key={index}
size='small'
control={
<Checkbox
disabled={eligibleUsecases.length === 0 ? true : !eligibleUsecases.includes(usecase)}
color='success'
checked={selectedUsecases.includes(usecase)}
onChange={(event) => {
setSelectedUsecases(
event.target.checked
? [...selectedUsecases, usecase]
: selectedUsecases.filter((item) => item !== usecase)
)
}}
/>
}
label={usecase}
/>
))}
</Stack>
{selectedUsecases.length > 0 && (
<Button
sx={{ width: 'max-content', borderRadius: '20px' }}
variant='outlined'
onClick={() => clearAllUsecases()}
startIcon={<IconX />}
>
Clear All
</Button>
)}
{!view || view === 'card' ? (
<>
{isLoading ? (
@@ -399,6 +480,7 @@ const Marketplace = () => {
.filter(filterByType)
.filter(filterFlows)
.filter(filterByFramework)
.filter(filterByUsecases)
.map((data, index) => (
<Box key={index}>
{data.badge && (
@@ -443,6 +525,7 @@ const Marketplace = () => {
filterByType={filterByType}
filterByBadge={filterByBadge}
filterByFramework={filterByFramework}
filterByUsecases={filterByUsecases}
goToTool={goToTool}
goToCanvas={goToCanvas}
isLoading={isLoading}