- Introduced loaderName property in IDocumentStoreUpsertData interface.

- Updated upsertDocStore function to utilize loaderName if provided.
- Enhanced DocStoreAPIDialog to allow loaderName customization in API requests.
- Modified DocumentStoreDetail to display file names when available, improving source formatting logic.
This commit is contained in:
Henry 2025-08-18 17:06:07 +08:00
parent 5d87ca98d1
commit 3a3a646462
4 changed files with 70 additions and 5 deletions

View File

@ -81,6 +81,7 @@ export interface IDocumentStoreUpsertData {
replaceExisting?: boolean replaceExisting?: boolean
createNewDocStore?: boolean createNewDocStore?: boolean
docStore?: IDocumentStore docStore?: IDocumentStore
loaderName?: string
loader?: { loader?: {
name: string name: string
config: ICommonObject config: ICommonObject

View File

@ -1728,6 +1728,11 @@ const upsertDocStore = async (
...newLoader?.config ...newLoader?.config
} }
// Override loaderName if it's provided directly in data
if (data.loaderName) {
loaderName = data.loaderName
}
splitterName = newSplitter?.name ? getComponentLabelFromName(newSplitter?.name) : splitterName splitterName = newSplitter?.name ? getComponentLabelFromName(newSplitter?.name) : splitterName
splitterId = newSplitter?.name || splitterId splitterId = newSplitter?.name || splitterId
splitterConfig = { splitterConfig = {

View File

@ -2,18 +2,32 @@ import { createPortal } from 'react-dom'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { MemoizedReactMarkdown } from '@/ui-component/markdown/MemoizedReactMarkdown' import { MemoizedReactMarkdown } from '@/ui-component/markdown/MemoizedReactMarkdown'
import { Typography, Stack, Card, Accordion, AccordionSummary, AccordionDetails, Dialog, DialogContent, DialogTitle } from '@mui/material' import {
Typography,
Stack,
Card,
Accordion,
AccordionSummary,
AccordionDetails,
Dialog,
DialogContent,
DialogTitle,
Box
} from '@mui/material'
import { TableViewOnly } from '@/ui-component/table/Table' import { TableViewOnly } from '@/ui-component/table/Table'
import documentstoreApi from '@/api/documentstore' import documentstoreApi from '@/api/documentstore'
import useApi from '@/hooks/useApi' import useApi from '@/hooks/useApi'
import { useTheme } from '@mui/material/styles' import { useTheme } from '@mui/material/styles'
import { useSelector } from 'react-redux'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore' import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { IconInfoCircle } from '@tabler/icons-react'
import { baseURL } from '@/store/constant' import { baseURL } from '@/store/constant'
const DocStoreAPIDialog = ({ show, dialogProps, onCancel }) => { const DocStoreAPIDialog = ({ show, dialogProps, onCancel }) => {
const [nodeConfig, setNodeConfig] = useState({}) const [nodeConfig, setNodeConfig] = useState({})
const [values, setValues] = useState('') const [values, setValues] = useState('')
const theme = useTheme() const theme = useTheme()
const customization = useSelector((state) => state.customization)
const [nodeConfigExpanded, setNodeConfigExpanded] = useState({}) const [nodeConfigExpanded, setNodeConfigExpanded] = useState({})
const getConfigApi = useApi(documentstoreApi.getDocumentStoreConfig) const getConfigApi = useApi(documentstoreApi.getDocumentStoreConfig)
@ -38,6 +52,7 @@ body_data = {
"metadata": {}, # Add additional metadata to the document chunks "metadata": {}, # Add additional metadata to the document chunks
"replaceExisting": True, # Replace existing document with the new upserted chunks "replaceExisting": True, # Replace existing document with the new upserted chunks
"createNewDocStore": False, # Create a new document store "createNewDocStore": False, # Create a new document store
"loaderName": "Custom Loader Name", # Override the loader name
"splitter": json.dumps({"config":{"chunkSize":20000}}) # Override existing configuration "splitter": json.dumps({"config":{"chunkSize":20000}}) # Override existing configuration
# "loader": "", # "loader": "",
# "vectorStore": "", # "vectorStore": "",
@ -64,6 +79,7 @@ print(output)
let formData = new FormData(); let formData = new FormData();
formData.append("files", input.files[0]); formData.append("files", input.files[0]);
formData.append("docId", "${dialogProps.loaderId}"); formData.append("docId", "${dialogProps.loaderId}");
formData.append("loaderName", "Custom Loader Name");
formData.append("splitter", JSON.stringify({"config":{"chunkSize":20000}})); formData.append("splitter", JSON.stringify({"config":{"chunkSize":20000}}));
// Add additional metadata to the document chunks // Add additional metadata to the document chunks
formData.append("metadata", "{}"); formData.append("metadata", "{}");
@ -103,6 +119,7 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
-H "Authorization: Bearer <your_api_key_here>" \\ -H "Authorization: Bearer <your_api_key_here>" \\
-F "files=@<file-path>" \\ -F "files=@<file-path>" \\
-F "docId=${dialogProps.loaderId}" \\ -F "docId=${dialogProps.loaderId}" \\
-F "loaderName=Custom Loader Name" \\
-F "splitter={"config":{"chunkSize":20000}}" \\ -F "splitter={"config":{"chunkSize":20000}}" \\
-F "metadata={}" \\ -F "metadata={}" \\
-F "replaceExisting=true" \\ -F "replaceExisting=true" \\
@ -139,6 +156,7 @@ output = query({
"metadata": "{}", # Add additional metadata to the document chunks "metadata": "{}", # Add additional metadata to the document chunks
"replaceExisting": True, # Replace existing document with the new upserted chunks "replaceExisting": True, # Replace existing document with the new upserted chunks
"createNewDocStore": False, # Create a new document store "createNewDocStore": False, # Create a new document store
"loaderName": "Custom Loader Name", # Override the loader name
# Override existing configuration # Override existing configuration
"loader": { "loader": {
"config": { "config": {
@ -176,10 +194,11 @@ async function query(data) {
} }
query({ query({
"docId": "${dialogProps.loaderId}, "docId": "${dialogProps.loaderId}",
"metadata": "{}", // Add additional metadata to the document chunks "metadata": "{}", // Add additional metadata to the document chunks
"replaceExisting": true, // Replace existing document with the new upserted chunks "replaceExisting": true, // Replace existing document with the new upserted chunks
"createNewDocStore": false, // Create a new document store "createNewDocStore": false, // Create a new document store
"loaderName": "Custom Loader Name", // Override the loader name
// Override existing configuration // Override existing configuration
"loader": { "loader": {
"config": { "config": {
@ -209,6 +228,7 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
"metadata": "{}", "metadata": "{}",
"replaceExisting": true, "replaceExisting": true,
"createNewDocStore": false, "createNewDocStore": false,
"loaderName": "Custom Loader Name",
"loader": { "loader": {
"config": { "config": {
"text": "This is a new text" "text": "This is a new text"
@ -304,6 +324,37 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
{dialogProps.title} {dialogProps.title}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
{/* Info Box */}
<Box
sx={{
display: 'flex',
alignItems: 'center',
padding: 2,
mb: 3,
background: customization.isDarkMode
? 'linear-gradient(135deg, rgba(33, 150, 243, 0.2) 0%, rgba(33, 150, 243, 0.1) 100%)'
: 'linear-gradient(135deg, rgba(33, 150, 243, 0.1) 0%, rgba(33, 150, 243, 0.05) 100%)',
color: customization.isDarkMode ? 'white' : '#333333',
fontWeight: 400,
borderRadius: 2,
border: `1px solid ${customization.isDarkMode ? 'rgba(33, 150, 243, 0.3)' : 'rgba(33, 150, 243, 0.2)'}`,
gap: 1.5
}}
>
<IconInfoCircle
size={20}
style={{
color: customization.isDarkMode ? '#64b5f6' : '#1976d2',
flexShrink: 0
}}
/>
<Box sx={{ flex: 1 }}>
<strong>Note:</strong> Upsert API can only be used when the existing document loader has been upserted before.
</Box>
</Box>
{/** info */}
<MemoizedReactMarkdown>{values}</MemoizedReactMarkdown> <MemoizedReactMarkdown>{values}</MemoizedReactMarkdown>
<Typography sx={{ mt: 3, mb: 1 }}>You can override existing configurations:</Typography> <Typography sx={{ mt: 3, mb: 1 }}>You can override existing configurations:</Typography>

View File

@ -756,14 +756,20 @@ function LoaderRow(props) {
setAnchorEl(null) setAnchorEl(null)
} }
const formatSources = (source) => { const formatSources = (files, source) => {
// Prefer files.name when files array exists and has items
if (files && Array.isArray(files) && files.length > 0) {
return files.map((file) => file.name).join(', ')
}
// Fallback to original source logic
if (source && typeof source === 'string' && source.includes('base64')) { if (source && typeof source === 'string' && source.includes('base64')) {
return getFileName(source) return getFileName(source)
} }
if (source && typeof source === 'string' && source.startsWith('[') && source.endsWith(']')) { if (source && typeof source === 'string' && source.startsWith('[') && source.endsWith(']')) {
return JSON.parse(source).join(', ') return JSON.parse(source).join(', ')
} }
return source return source || 'No source'
} }
return ( return (
@ -784,7 +790,9 @@ function LoaderRow(props) {
{props.loader.loaderName} {props.loader.loaderName}
</StyledTableCell> </StyledTableCell>
<StyledTableCell onClick={props.onViewChunksClick}>{props.loader.splitterName ?? 'None'}</StyledTableCell> <StyledTableCell onClick={props.onViewChunksClick}>{props.loader.splitterName ?? 'None'}</StyledTableCell>
<StyledTableCell onClick={props.onViewChunksClick}>{formatSources(props.loader.source)}</StyledTableCell> <StyledTableCell onClick={props.onViewChunksClick}>
{formatSources(props.loader.files, props.loader.source)}
</StyledTableCell>
<StyledTableCell onClick={props.onViewChunksClick}> <StyledTableCell onClick={props.onViewChunksClick}>
{props.loader.totalChunks && <Chip variant='outlined' size='small' label={props.loader.totalChunks.toLocaleString()} />} {props.loader.totalChunks && <Chip variant='outlined' size='small' label={props.loader.totalChunks.toLocaleString()} />}
</StyledTableCell> </StyledTableCell>