mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 13:00:56 +03:00
Feature/Indexing (#1802)
* indexing * fix for multiple files upsert * fix default Postgres port * fix SQLite node description * add MySQLRecordManager node * fix MySQL unique index * add upsert history * update jsx ui * lint-fix * update dialog details * update llamaindex pinecone --------- Co-authored-by: chungyau97 <chungyau97@gmail.com>
This commit is contained in:
@@ -93,6 +93,14 @@ export interface IVariable {
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
export interface IUpsertHistory {
|
||||
id: string
|
||||
chatflowid: string
|
||||
result: string
|
||||
flowData: string
|
||||
date: Date
|
||||
}
|
||||
|
||||
export interface IComponentNodes {
|
||||
[key: string]: INode
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ const creatTool = async (req: Request, res: Response, next: NextFunction) => {
|
||||
const deleteTool = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
if (typeof req.params.id === 'undefined' || req.params.id === '') {
|
||||
throw new Error(`Error: toolsController.updateTool - id not provided!`)
|
||||
throw new Error(`Error: toolsController.deleteTool - id not provided!`)
|
||||
}
|
||||
const apiResponse = await toolsService.deleteTool(req.params.id)
|
||||
if (apiResponse.executionError) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Request, Response, NextFunction } from 'express'
|
||||
import upsertHistoryService from '../../services/upsert-history'
|
||||
|
||||
const getAllUpsertHistory = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const sortOrder = req.query?.order as string | undefined
|
||||
const chatflowid = req.params?.id as string | undefined
|
||||
const startDate = req.query?.startDate as string | undefined
|
||||
const endDate = req.query?.endDate as string | undefined
|
||||
const apiResponse = await upsertHistoryService.getAllUpsertHistory(sortOrder, chatflowid, startDate, endDate)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const patchDeleteUpsertHistory = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const ids = req.body.ids ?? []
|
||||
const apiResponse = await upsertHistoryService.patchDeleteUpsertHistory(ids)
|
||||
return res.json(apiResponse)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllUpsertHistory,
|
||||
patchDeleteUpsertHistory
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export class Assistant implements IAssistant {
|
||||
@Column({ type: 'text' })
|
||||
details: string
|
||||
|
||||
@Column({ type: 'uuid'})
|
||||
@Column({ type: 'uuid' })
|
||||
credential: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
|
||||
@@ -34,11 +34,11 @@ export class ChatFlow implements IChatFlow {
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
speechToText?: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export class ChatMessage implements IChatMessage {
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
sessionId?: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export class ChatMessageFeedback implements IChatMessageFeedback {
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
content?: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ export class Credential implements ICredential {
|
||||
@Column({ type: 'text' })
|
||||
encryptedData: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ export class Tool implements ITool {
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
func?: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable */
|
||||
import { Entity, Column, PrimaryGeneratedColumn, Index, CreateDateColumn } from 'typeorm'
|
||||
import { IUpsertHistory } from '../../Interface'
|
||||
|
||||
@Entity()
|
||||
export class UpsertHistory implements IUpsertHistory {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string
|
||||
|
||||
@Index()
|
||||
@Column()
|
||||
chatflowid: string
|
||||
|
||||
@Column()
|
||||
result: string
|
||||
|
||||
@Column()
|
||||
flowData: string
|
||||
|
||||
@CreateDateColumn()
|
||||
date: Date
|
||||
}
|
||||
@@ -16,11 +16,11 @@ export class Variable implements IVariable {
|
||||
@Column({ default: 'string', type: 'text' })
|
||||
type: string
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
|
||||
@Column({type:'timestamp'})
|
||||
@Column({ type: 'timestamp' })
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Credential } from './Credential'
|
||||
import { Tool } from './Tool'
|
||||
import { Assistant } from './Assistant'
|
||||
import { Variable } from './Variable'
|
||||
import { UpsertHistory } from './UpsertHistory'
|
||||
|
||||
export const entities = {
|
||||
ChatFlow,
|
||||
@@ -13,5 +14,6 @@ export const entities = {
|
||||
Credential,
|
||||
Tool,
|
||||
Assistant,
|
||||
Variable
|
||||
Variable,
|
||||
UpsertHistory
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddUpsertHistoryEntity1709814301358 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS \`upsert_history\` (
|
||||
\`id\` varchar(36) NOT NULL,
|
||||
\`chatflowid\` varchar(255) NOT NULL,
|
||||
\`result\` text NOT NULL,
|
||||
\`flowData\` text NOT NULL,
|
||||
\`date\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (\`id\`)
|
||||
KEY \`IDX_a0b59fd66f6e48d2b198123cb6\` (\`chatflowid\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE upsert_history`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddUpsertHistoryEntity1709814301358 } from './1709814301358-AddUpsertHistoryEntity'
|
||||
import { AddFeedback1707213626553 } from './1707213626553-AddFeedback'
|
||||
|
||||
export const mysqlMigrations = [
|
||||
@@ -31,5 +32,6 @@ export const mysqlMigrations = [
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060,
|
||||
AddUpsertHistoryEntity1709814301358,
|
||||
AddFeedback1707213626553
|
||||
]
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddUpsertHistoryEntity1709814301358 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS upsert_history (
|
||||
id uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
"chatflowid" varchar NOT NULL,
|
||||
"result" text NOT NULL,
|
||||
"flowData" text NOT NULL,
|
||||
"date" timestamp NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "PK_37327b22b6e246319bd5eeb0e88" PRIMARY KEY (id)
|
||||
);`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE upsert_history`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddUpsertHistoryEntity1709814301358 } from './1709814301358-AddUpsertHistoryEntity'
|
||||
import { AddFeedback1707213601923 } from './1707213601923-AddFeedback'
|
||||
import { FieldTypes1710497452584 } from './1710497452584-FieldTypes'
|
||||
|
||||
@@ -32,6 +33,7 @@ export const postgresMigrations = [
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060,
|
||||
AddUpsertHistoryEntity1709814301358,
|
||||
AddFeedback1707213601923,
|
||||
FieldTypes1710497452584
|
||||
]
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddUpsertHistoryEntity1709814301358 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS "upsert_history" ("id" varchar PRIMARY KEY NOT NULL, "chatflowid" varchar NOT NULL, "result" text NOT NULL, "flowData" text NOT NULL, "date" datetime NOT NULL DEFAULT (datetime('now')));`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE upsert_history`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddUpsertHistoryEntity1709814301358 } from './1709814301358-AddUpsertHistoryEntity'
|
||||
import { AddFeedback1707213619308 } from './1707213619308-AddFeedback'
|
||||
|
||||
export const sqliteMigrations = [
|
||||
@@ -31,5 +32,6 @@ export const sqliteMigrations = [
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060,
|
||||
AddUpsertHistoryEntity1709814301358,
|
||||
AddFeedback1707213619308
|
||||
]
|
||||
|
||||
@@ -35,6 +35,7 @@ import variablesRouter from './variables'
|
||||
import vectorRouter from './vectors'
|
||||
import verifyRouter from './verify'
|
||||
import versionRouter from './versions'
|
||||
import upsertHistoryRouter from './upsert-history'
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
@@ -74,5 +75,6 @@ router.use('/variables', variablesRouter)
|
||||
router.use('/vector', vectorRouter)
|
||||
router.use('/verify', verifyRouter)
|
||||
router.use('/version', versionRouter)
|
||||
router.use('/upsert-history', upsertHistoryRouter)
|
||||
|
||||
export default router
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import express from 'express'
|
||||
import upsertHistoryController from '../../controllers/upsert-history'
|
||||
const router = express.Router()
|
||||
|
||||
// CREATE
|
||||
|
||||
// READ
|
||||
router.get('/:id', upsertHistoryController.getAllUpsertHistory)
|
||||
|
||||
// PATCH
|
||||
router.patch('/', upsertHistoryController.patchDeleteUpsertHistory)
|
||||
|
||||
// DELETE
|
||||
|
||||
export default router
|
||||
@@ -14,6 +14,9 @@ import logger from '../../utils/logger'
|
||||
import { getStoragePath } from 'flowise-components'
|
||||
import { IReactFlowObject } from '../../Interface'
|
||||
import { utilGetUploadsConfig } from '../../utils/getUploadsConfig'
|
||||
import { ChatMessage } from '../../database/entities/ChatMessage'
|
||||
import { ChatMessageFeedback } from '../../database/entities/ChatMessageFeedback'
|
||||
import { UpsertHistory } from '../../database/entities/UpsertHistory'
|
||||
|
||||
// Check if chatflow valid for streaming
|
||||
const checkIfChatflowIsValidForStreaming = async (chatflowId: string): Promise<any> => {
|
||||
@@ -105,9 +108,18 @@ const deleteChatflow = async (chatflowId: string): Promise<any> => {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).delete({ id: chatflowId })
|
||||
try {
|
||||
// Delete all uploads corresponding to this chatflow
|
||||
// Delete all uploads corresponding to this chatflow
|
||||
const directory = path.join(getStoragePath(), chatflowId)
|
||||
deleteFolderRecursive(directory)
|
||||
|
||||
// Delete all chat messages
|
||||
await appServer.AppDataSource.getRepository(ChatMessage).delete({ chatflowid: chatflowId })
|
||||
|
||||
// Delete all chat feedback
|
||||
await appServer.AppDataSource.getRepository(ChatMessageFeedback).delete({ chatflowid: chatflowId })
|
||||
|
||||
// Delete all upsert history
|
||||
await appServer.AppDataSource.getRepository(UpsertHistory).delete({ chatflowid: chatflowId })
|
||||
} catch (e) {
|
||||
logger.error(`[server]: Error deleting file storage for chatflow ${chatflowId}: ${e}`)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { MoreThanOrEqual, LessThanOrEqual } from 'typeorm'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { UpsertHistory } from '../../database/entities/UpsertHistory'
|
||||
|
||||
const getAllUpsertHistory = async (
|
||||
sortOrder: string | undefined,
|
||||
chatflowid: string | undefined,
|
||||
startDate: string | undefined,
|
||||
endDate: string | undefined
|
||||
) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
|
||||
const setDateToStartOrEndOfDay = (dateTimeStr: string, setHours: 'start' | 'end') => {
|
||||
const date = new Date(dateTimeStr)
|
||||
if (isNaN(date.getTime())) {
|
||||
return undefined
|
||||
}
|
||||
setHours === 'start' ? date.setHours(0, 0, 0, 0) : date.setHours(23, 59, 59, 999)
|
||||
return date
|
||||
}
|
||||
|
||||
let fromDate
|
||||
if (startDate) fromDate = setDateToStartOrEndOfDay(startDate, 'start')
|
||||
|
||||
let toDate
|
||||
if (endDate) toDate = setDateToStartOrEndOfDay(endDate, 'end')
|
||||
|
||||
let upsertHistory = await appServer.AppDataSource.getRepository(UpsertHistory).find({
|
||||
where: {
|
||||
chatflowid,
|
||||
...(fromDate && { date: MoreThanOrEqual(fromDate) }),
|
||||
...(toDate && { date: LessThanOrEqual(toDate) })
|
||||
},
|
||||
order: {
|
||||
date: sortOrder === 'DESC' ? 'DESC' : 'ASC'
|
||||
}
|
||||
})
|
||||
upsertHistory = upsertHistory.map((hist) => {
|
||||
return {
|
||||
...hist,
|
||||
result: hist.result ? JSON.parse(hist.result) : {},
|
||||
flowData: hist.flowData ? JSON.parse(hist.flowData) : {}
|
||||
}
|
||||
})
|
||||
|
||||
return upsertHistory
|
||||
} catch (error) {
|
||||
throw new Error(`Error: upsertHistoryServices.getAllUpsertHistory - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const patchDeleteUpsertHistory = async (ids: string[] = []): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(UpsertHistory).delete(ids)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: upsertHistoryServices.patchUpsertHistory - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllUpsertHistory,
|
||||
patchDeleteUpsertHistory
|
||||
}
|
||||
@@ -18,7 +18,7 @@ const deleteVariable = async (variableId: string): Promise<any> => {
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).delete({ id: variableId })
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.createVariable - ${error}`)
|
||||
throw new Error(`Error: variablesServices.deleteVariable - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ import { utilAddChatMessage } from './addChatMesage'
|
||||
* @param {Request} req
|
||||
* @param {Server} socketIO
|
||||
* @param {boolean} isInternal
|
||||
* @param {boolean} isUpsert
|
||||
*/
|
||||
export const utilBuildChatflow = async (req: Request, socketIO?: Server, isInternal: boolean = false): Promise<any> => {
|
||||
try {
|
||||
|
||||
@@ -237,6 +237,84 @@ export const getEndingNodes = (nodeDependencies: INodeDependencies, graph: INode
|
||||
return endingNodeIds
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file name from base64 string
|
||||
* @param {string} fileBase64
|
||||
*/
|
||||
export const getFileName = (fileBase64: string): string => {
|
||||
let fileNames = []
|
||||
if (fileBase64.startsWith('[') && fileBase64.endsWith(']')) {
|
||||
const files = JSON.parse(fileBase64)
|
||||
for (const file of files) {
|
||||
const splitDataURI = file.split(',')
|
||||
const filename = splitDataURI[splitDataURI.length - 1].split(':')[1]
|
||||
fileNames.push(filename)
|
||||
}
|
||||
return fileNames.join(', ')
|
||||
} else {
|
||||
const splitDataURI = fileBase64.split(',')
|
||||
const filename = splitDataURI[splitDataURI.length - 1].split(':')[1]
|
||||
return filename
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save upsert flowData
|
||||
* @param {INodeData} nodeData
|
||||
* @param {Record<string, any>} upsertHistory
|
||||
*/
|
||||
export const saveUpsertFlowData = (nodeData: INodeData, upsertHistory: Record<string, any>): ICommonObject[] => {
|
||||
const existingUpsertFlowData = upsertHistory['flowData'] ?? []
|
||||
const paramValues: ICommonObject[] = []
|
||||
|
||||
for (const input in nodeData.inputs) {
|
||||
const inputParam = nodeData.inputParams.find((inp) => inp.name === input)
|
||||
if (!inputParam) continue
|
||||
|
||||
let paramValue: ICommonObject = {}
|
||||
|
||||
if (!nodeData.inputs[input]) {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
typeof nodeData.inputs[input] === 'string' &&
|
||||
nodeData.inputs[input].startsWith('{{') &&
|
||||
nodeData.inputs[input].endsWith('}}')
|
||||
) {
|
||||
continue
|
||||
}
|
||||
// Get file name instead of the base64 string
|
||||
if (nodeData.category === 'Document Loaders' && nodeData.inputParams.find((inp) => inp.name === input)?.type === 'file') {
|
||||
paramValue = {
|
||||
label: inputParam?.label,
|
||||
name: inputParam?.name,
|
||||
type: inputParam?.type,
|
||||
value: getFileName(nodeData.inputs[input])
|
||||
}
|
||||
paramValues.push(paramValue)
|
||||
continue
|
||||
}
|
||||
|
||||
paramValue = {
|
||||
label: inputParam?.label,
|
||||
name: inputParam?.name,
|
||||
type: inputParam?.type,
|
||||
value: nodeData.inputs[input]
|
||||
}
|
||||
paramValues.push(paramValue)
|
||||
}
|
||||
|
||||
const newFlowData = {
|
||||
label: nodeData.label,
|
||||
name: nodeData.name,
|
||||
category: nodeData.category,
|
||||
id: nodeData.id,
|
||||
paramValues
|
||||
}
|
||||
existingUpsertFlowData.push(newFlowData)
|
||||
return existingUpsertFlowData
|
||||
}
|
||||
|
||||
/**
|
||||
* Build langchain from start to end
|
||||
* @param {string[]} startingNodeIds
|
||||
@@ -272,6 +350,8 @@ export const buildFlow = async (
|
||||
) => {
|
||||
const flowNodes = cloneDeep(reactFlowNodes)
|
||||
|
||||
let upsertHistory: Record<string, any> = {}
|
||||
|
||||
// Create a Queue and add our initial node in it
|
||||
const nodeQueue = [] as INodeQueue[]
|
||||
const exploredNode = {} as IExploredNode
|
||||
@@ -302,12 +382,15 @@ export const buildFlow = async (
|
||||
|
||||
let flowNodeData = cloneDeep(reactFlowNode.data)
|
||||
if (overrideConfig) flowNodeData = replaceInputsWithConfig(flowNodeData, overrideConfig)
|
||||
|
||||
if (isUpsert) upsertHistory['flowData'] = saveUpsertFlowData(flowNodeData, upsertHistory)
|
||||
|
||||
const reactFlowNodeData: INodeData = resolveVariables(flowNodeData, flowNodes, question, chatHistory)
|
||||
|
||||
// TODO: Avoid processing Text Splitter + Doc Loader once Upsert & Load Existing Vector Nodes are deprecated
|
||||
if (isUpsert && stopNodeId && nodeId === stopNodeId) {
|
||||
logger.debug(`[server]: Upserting ${reactFlowNode.data.label} (${reactFlowNode.data.id})`)
|
||||
await newNodeInstance.vectorStoreMethods!['upsert']!.call(newNodeInstance, reactFlowNodeData, {
|
||||
const indexResult = await newNodeInstance.vectorStoreMethods!['upsert']!.call(newNodeInstance, reactFlowNodeData, {
|
||||
chatId,
|
||||
sessionId,
|
||||
chatflowid,
|
||||
@@ -319,6 +402,7 @@ export const buildFlow = async (
|
||||
dynamicVariables,
|
||||
uploads
|
||||
})
|
||||
if (indexResult) upsertHistory['result'] = indexResult
|
||||
logger.debug(`[server]: Finished upserting ${reactFlowNode.data.label} (${reactFlowNode.data.id})`)
|
||||
break
|
||||
} else {
|
||||
@@ -422,7 +506,7 @@ export const buildFlow = async (
|
||||
flowNodes.push(flowNodes.splice(index, 1)[0])
|
||||
}
|
||||
}
|
||||
return flowNodes
|
||||
return isUpsert ? (upsertHistory as any) : flowNodes
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Request, Response } from 'express'
|
||||
import * as fs from 'fs'
|
||||
import { cloneDeep, omit } from 'lodash'
|
||||
import { ICommonObject } from 'flowise-components'
|
||||
import telemetryService from '../services/telemetry'
|
||||
import logger from '../utils/logger'
|
||||
@@ -18,7 +19,14 @@ import { utilValidateKey } from './validateKey'
|
||||
import { IncomingInput, INodeDirectedGraph, IReactFlowObject, chatType } from '../Interface'
|
||||
import { ChatFlow } from '../database/entities/ChatFlow'
|
||||
import { getRunningExpressApp } from '../utils/getRunningExpressApp'
|
||||
import { UpsertHistory } from '../database/entities/UpsertHistory'
|
||||
|
||||
/**
|
||||
* Upsert documents
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {boolean} isInternal
|
||||
*/
|
||||
export const upsertVector = async (req: Request, res: Response, isInternal: boolean = false) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
@@ -78,6 +86,8 @@ export const upsertVector = async (req: Request, res: Response, isInternal: bool
|
||||
(node) =>
|
||||
node.data.category === 'Vector Stores' && !node.data.label.includes('Upsert') && !node.data.label.includes('Load Existing')
|
||||
)
|
||||
|
||||
// Check if multiple vector store nodes exist, and if stopNodeId is specified
|
||||
if (vsNodes.length > 1 && !stopNodeId) {
|
||||
return res.status(500).send('There are multiple vector nodes, please provide stopNodeId in body request')
|
||||
} else if (vsNodes.length === 1 && !stopNodeId) {
|
||||
@@ -99,7 +109,7 @@ export const upsertVector = async (req: Request, res: Response, isInternal: bool
|
||||
|
||||
const { startingNodeIds, depthQueue } = getStartingNodes(filteredGraph, stopNodeId)
|
||||
|
||||
await buildFlow(
|
||||
const upsertedResult = await buildFlow(
|
||||
startingNodeIds,
|
||||
nodes,
|
||||
edges,
|
||||
@@ -121,6 +131,19 @@ export const upsertVector = async (req: Request, res: Response, isInternal: bool
|
||||
const startingNodes = nodes.filter((nd) => startingNodeIds.includes(nd.data.id))
|
||||
|
||||
await appServer.chatflowPool.add(chatflowid, undefined, startingNodes, incomingInput?.overrideConfig)
|
||||
|
||||
// Save to DB
|
||||
if (upsertedResult['flowData'] && upsertedResult['result']) {
|
||||
const result = cloneDeep(upsertedResult)
|
||||
result['flowData'] = JSON.stringify(result['flowData'])
|
||||
result['result'] = JSON.stringify(omit(result['result'], ['totalKeys', 'addedDocs']))
|
||||
result.chatflowid = chatflowid
|
||||
const newUpsertHistory = new UpsertHistory()
|
||||
Object.assign(newUpsertHistory, result)
|
||||
const upsertHistory = appServer.AppDataSource.getRepository(UpsertHistory).create(newUpsertHistory)
|
||||
await appServer.AppDataSource.getRepository(UpsertHistory).save(upsertHistory)
|
||||
}
|
||||
|
||||
await telemetryService.createEvent({
|
||||
name: `vector_upserted`,
|
||||
data: {
|
||||
@@ -131,7 +154,7 @@ export const upsertVector = async (req: Request, res: Response, isInternal: bool
|
||||
stopNodeId
|
||||
}
|
||||
})
|
||||
return res.status(201).send('Successfully Upserted')
|
||||
return res.status(201).json(upsertedResult['result'] ?? { result: 'Successfully Upserted' })
|
||||
} catch (e: any) {
|
||||
logger.error('[server]: Error:', e)
|
||||
return res.status(500).send(e.message)
|
||||
|
||||
Reference in New Issue
Block a user