mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 19:00:59 +03:00
Merge branch 'main' into FEATURE/Vision
# Conflicts: # packages/server/src/database/migrations/mysql/index.ts # packages/server/src/database/migrations/postgres/index.ts # packages/server/src/database/migrations/sqlite/index.ts
This commit is contained in:
@@ -12,6 +12,7 @@ PORT=3000
|
||||
# DATABASE_NAME="flowise"
|
||||
# DATABASE_USER=""
|
||||
# DATABASE_PASSWORD=""
|
||||
# DATABASE_SSL=true
|
||||
|
||||
# FLOWISE_USERNAME=user
|
||||
# FLOWISE_PASSWORD=1234
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"data": {
|
||||
"id": "openAIAssistant_0",
|
||||
"label": "OpenAI Assistant",
|
||||
"version": 2,
|
||||
"version": 3,
|
||||
"name": "openAIAssistant",
|
||||
"type": "OpenAIAssistant",
|
||||
"baseClasses": ["OpenAIAssistant"],
|
||||
@@ -45,6 +45,15 @@
|
||||
"type": "Tool",
|
||||
"list": true,
|
||||
"id": "openAIAssistant_0-input-tools-Tool"
|
||||
},
|
||||
{
|
||||
"label": "Input Moderation",
|
||||
"description": "Detect text that could generate harmful output and prevent it from being sent to the language model",
|
||||
"name": "inputModeration",
|
||||
"type": "Moderation",
|
||||
"optional": true,
|
||||
"list": true,
|
||||
"id": "openAIAssistant_0-input-inputModeration-Moderation"
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flowise",
|
||||
"version": "1.4.7",
|
||||
"version": "1.4.9",
|
||||
"description": "Flowiseai Server",
|
||||
"main": "dist/index",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -46,6 +46,7 @@ export const init = async (): Promise<void> => {
|
||||
username: process.env.DATABASE_USER,
|
||||
password: process.env.DATABASE_PASSWORD,
|
||||
database: process.env.DATABASE_NAME,
|
||||
ssl: process.env.DATABASE_SSL === 'true',
|
||||
synchronize: false,
|
||||
migrationsRun: false,
|
||||
entities: Object.values(entities),
|
||||
|
||||
@@ -69,6 +69,15 @@ export interface ICredential {
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
export interface IVariable {
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
type: string
|
||||
updatedDate: Date
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
export interface IComponentNodes {
|
||||
[key: string]: INode
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ export default class Start extends Command {
|
||||
DATABASE_NAME: Flags.string(),
|
||||
DATABASE_USER: Flags.string(),
|
||||
DATABASE_PASSWORD: Flags.string(),
|
||||
DATABASE_SSL: Flags.string(),
|
||||
LANGCHAIN_TRACING_V2: Flags.string(),
|
||||
LANGCHAIN_ENDPOINT: Flags.string(),
|
||||
LANGCHAIN_API_KEY: Flags.string(),
|
||||
@@ -104,6 +105,7 @@ export default class Start extends Command {
|
||||
if (flags.DATABASE_NAME) process.env.DATABASE_NAME = flags.DATABASE_NAME
|
||||
if (flags.DATABASE_USER) process.env.DATABASE_USER = flags.DATABASE_USER
|
||||
if (flags.DATABASE_PASSWORD) process.env.DATABASE_PASSWORD = flags.DATABASE_PASSWORD
|
||||
if (flags.DATABASE_SSL) process.env.DATABASE_SSL = flags.DATABASE_SSL
|
||||
|
||||
// Langsmith tracing
|
||||
if (flags.LANGCHAIN_TRACING_V2) process.env.LANGCHAIN_TRACING_V2 = flags.LANGCHAIN_TRACING_V2
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* eslint-disable */
|
||||
import { Entity, Column, CreateDateColumn, UpdateDateColumn, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { IVariable } from '../../Interface'
|
||||
|
||||
@Entity()
|
||||
export class Variable implements IVariable {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string
|
||||
|
||||
@Column()
|
||||
name: string
|
||||
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
value: string
|
||||
|
||||
@Column({ default: 'string', type: 'text' })
|
||||
type: string
|
||||
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date
|
||||
}
|
||||
@@ -3,11 +3,13 @@ import { ChatMessage } from './ChatMessage'
|
||||
import { Credential } from './Credential'
|
||||
import { Tool } from './Tool'
|
||||
import { Assistant } from './Assistant'
|
||||
import { Variable } from './Variable'
|
||||
|
||||
export const entities = {
|
||||
ChatFlow,
|
||||
ChatMessage,
|
||||
Credential,
|
||||
Tool,
|
||||
Assistant
|
||||
Assistant,
|
||||
Variable
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddVariableEntity1699325775451 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS \`variable\` (
|
||||
\`id\` varchar(36) NOT NULL,
|
||||
\`name\` varchar(255) NOT NULL,
|
||||
\`value\` text NOT NULL,
|
||||
\`type\` varchar(255) DEFAULT NULL,
|
||||
\`createdDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
\`updatedDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (\`id\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE variable`)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { AddUsedToolsToChatMessage1699481607341 } from './1699481607341-AddUsedT
|
||||
import { AddCategoryToChatFlow1699900910291 } from './1699900910291-AddCategoryToChatFlow'
|
||||
import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-AddFileAnnotationsToChatMessage'
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
|
||||
export const mysqlMigrations = [
|
||||
Init1693840429259,
|
||||
@@ -25,5 +26,6 @@ export const mysqlMigrations = [
|
||||
AddUsedToolsToChatMessage1699481607341,
|
||||
AddCategoryToChatFlow1699900910291,
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451
|
||||
]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddVariableEntity1699325775451 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS variable (
|
||||
id uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
"name" varchar NOT NULL,
|
||||
"value" text NOT NULL,
|
||||
"type" text NULL,
|
||||
"createdDate" timestamp NOT NULL DEFAULT now(),
|
||||
"updatedDate" timestamp NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "PK_98419043dd704f54-9830ab78f8" PRIMARY KEY (id)
|
||||
);`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE variable`)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { AddUsedToolsToChatMessage1699481607341 } from './1699481607341-AddUsedT
|
||||
import { AddCategoryToChatFlow1699900910291 } from './1699900910291-AddCategoryToChatFlow'
|
||||
import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-AddFileAnnotationsToChatMessage'
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
|
||||
export const postgresMigrations = [
|
||||
Init1693891895163,
|
||||
@@ -25,5 +26,6 @@ export const postgresMigrations = [
|
||||
AddUsedToolsToChatMessage1699481607341,
|
||||
AddCategoryToChatFlow1699900910291,
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451
|
||||
]
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddVariableEntity1699325775451 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS "variable" ("id" varchar PRIMARY KEY NOT NULL, "name" text NOT NULL, "value" text NOT NULL, "type" varchar, "createdDate" datetime NOT NULL DEFAULT (datetime('now')), "updatedDate" datetime NOT NULL DEFAULT (datetime('now')));`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE variable`)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { AddUsedToolsToChatMessage1699481607341 } from './1699481607341-AddUsedT
|
||||
import { AddCategoryToChatFlow1699900910291 } from './1699900910291-AddCategoryToChatFlow'
|
||||
import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-AddFileAnnotationsToChatMessage'
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
|
||||
export const sqliteMigrations = [
|
||||
Init1693835579790,
|
||||
@@ -25,5 +26,6 @@ export const sqliteMigrations = [
|
||||
AddUsedToolsToChatMessage1699481607341,
|
||||
AddCategoryToChatFlow1699900910291,
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451
|
||||
]
|
||||
|
||||
@@ -65,6 +65,7 @@ import { sanitizeMiddleware } from './utils/XSS'
|
||||
import axios from 'axios'
|
||||
import { Client } from 'langchainhub'
|
||||
import { parsePrompt } from './utils/hub'
|
||||
import { Variable } from './database/entities/Variable'
|
||||
|
||||
export class App {
|
||||
app: express.Application
|
||||
@@ -1227,6 +1228,47 @@ export class App {
|
||||
return res.json(templates)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Variables
|
||||
// ----------------------------------------
|
||||
this.app.get('/api/v1/variables', async (req: Request, res: Response) => {
|
||||
const variables = await getDataSource().getRepository(Variable).find()
|
||||
return res.json(variables)
|
||||
})
|
||||
|
||||
// Create new variable
|
||||
this.app.post('/api/v1/variables', async (req: Request, res: Response) => {
|
||||
const body = req.body
|
||||
const newVariable = new Variable()
|
||||
Object.assign(newVariable, body)
|
||||
const variable = this.AppDataSource.getRepository(Variable).create(newVariable)
|
||||
const results = await this.AppDataSource.getRepository(Variable).save(variable)
|
||||
return res.json(results)
|
||||
})
|
||||
|
||||
// Update variable
|
||||
this.app.put('/api/v1/variables/:id', async (req: Request, res: Response) => {
|
||||
const variable = await this.AppDataSource.getRepository(Variable).findOneBy({
|
||||
id: req.params.id
|
||||
})
|
||||
|
||||
if (!variable) return res.status(404).send(`Variable ${req.params.id} not found`)
|
||||
|
||||
const body = req.body
|
||||
const updateVariable = new Variable()
|
||||
Object.assign(updateVariable, body)
|
||||
this.AppDataSource.getRepository(Variable).merge(variable, updateVariable)
|
||||
const result = await this.AppDataSource.getRepository(Variable).save(variable)
|
||||
|
||||
return res.json(result)
|
||||
})
|
||||
|
||||
// Delete variable via id
|
||||
this.app.delete('/api/v1/variables/:id', async (req: Request, res: Response) => {
|
||||
const results = await this.AppDataSource.getRepository(Variable).delete({ id: req.params.id })
|
||||
return res.json(results)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// API Keys
|
||||
// ----------------------------------------
|
||||
@@ -1658,9 +1700,9 @@ export class App {
|
||||
|
||||
if (endingNodeData && endingNodeData.category !== 'Chains' && endingNodeData.category !== 'Agents') {
|
||||
if (endingNodeData.type !== 'OpenAIMultiModalChain') {
|
||||
return res.status(500).send(`Ending node must be either a Chain or Agent`)
|
||||
return res.status(500).send(`Ending node must be either a Chain or Agent`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
endingNodeData.outputs &&
|
||||
@@ -1749,10 +1791,6 @@ export class App {
|
||||
this.chatflowPool.add(chatflowid, nodeToExecuteData, startingNodes, incomingInput?.overrideConfig)
|
||||
}
|
||||
|
||||
const nodeInstanceFilePath = this.nodesPool.componentNodes[nodeToExecuteData.name].filePath as string
|
||||
const nodeModule = await import(nodeInstanceFilePath)
|
||||
const nodeInstance = new nodeModule.nodeClass()
|
||||
|
||||
logger.debug(`[server]: Running ${nodeToExecuteData.label} (${nodeToExecuteData.id})`)
|
||||
|
||||
let sessionId = undefined
|
||||
@@ -1766,6 +1804,10 @@ export class App {
|
||||
chatHistory = await replaceChatHistory(memoryNode, incomingInput, this.AppDataSource, databaseEntities, logger)
|
||||
}
|
||||
|
||||
const nodeInstanceFilePath = this.nodesPool.componentNodes[nodeToExecuteData.name].filePath as string
|
||||
const nodeModule = await import(nodeInstanceFilePath)
|
||||
const nodeInstance = new nodeModule.nodeClass({ sessionId })
|
||||
|
||||
let result = isStreamValid
|
||||
? await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||
uploads: incomingInput.uploads,
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
convertChatHistoryToText,
|
||||
getInputVariables,
|
||||
handleEscapeCharacters,
|
||||
getEncryptionKeyPath,
|
||||
ICommonObject,
|
||||
IDatabaseEntity,
|
||||
IMessage
|
||||
@@ -37,6 +38,7 @@ import { Tool } from '../database/entities/Tool'
|
||||
import { Assistant } from '../database/entities/Assistant'
|
||||
import { DataSource } from 'typeorm'
|
||||
import { CachePool } from '../CachePool'
|
||||
import { Variable } from '../database/entities/Variable'
|
||||
|
||||
const QUESTION_VAR_PREFIX = 'question'
|
||||
const CHAT_HISTORY_VAR_PREFIX = 'chat_history'
|
||||
@@ -47,7 +49,8 @@ export const databaseEntities: IDatabaseEntity = {
|
||||
ChatMessage: ChatMessage,
|
||||
Tool: Tool,
|
||||
Credential: Credential,
|
||||
Assistant: Assistant
|
||||
Assistant: Assistant,
|
||||
Variable: Variable
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,7 +561,11 @@ export const getVariableValue = (
|
||||
variablePaths.forEach((path) => {
|
||||
const variableValue = variableDict[path]
|
||||
// Replace all occurrence
|
||||
returnVal = returnVal.split(path).join(variableValue)
|
||||
if (typeof variableValue === 'object') {
|
||||
returnVal = returnVal.split(path).join(JSON.stringify(variableValue).replace(/"/g, '\\"'))
|
||||
} else {
|
||||
returnVal = returnVal.split(path).join(variableValue)
|
||||
}
|
||||
})
|
||||
return returnVal
|
||||
}
|
||||
@@ -815,7 +822,7 @@ export const findAvailableConfigs = (reactFlowNodes: IReactFlowNode[], component
|
||||
*/
|
||||
export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNodeData: INodeData) => {
|
||||
const streamAvailableLLMs = {
|
||||
'Chat Models': ['azureChatOpenAI', 'chatOpenAI', 'chatAnthropic', 'chatOllama', 'awsChatBedrock'],
|
||||
'Chat Models': ['azureChatOpenAI', 'chatOpenAI', 'chatAnthropic', 'chatOllama', 'awsChatBedrock', 'chatMistralAI'],
|
||||
LLMs: ['azureOpenAI', 'openAI', 'ollama']
|
||||
}
|
||||
|
||||
@@ -852,16 +859,6 @@ export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNod
|
||||
return isChatOrLLMsExist && isValidChainOrAgent && !isOutputParserExist
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of encryption key
|
||||
* @returns {string}
|
||||
*/
|
||||
export const getEncryptionKeyPath = (): string => {
|
||||
return process.env.SECRETKEY_PATH
|
||||
? path.join(process.env.SECRETKEY_PATH, 'encryption.key')
|
||||
: path.join(__dirname, '..', '..', 'encryption.key')
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an encryption key
|
||||
* @returns {string}
|
||||
@@ -882,7 +879,10 @@ export const getEncryptionKey = async (): Promise<string> => {
|
||||
return await fs.promises.readFile(getEncryptionKeyPath(), 'utf8')
|
||||
} catch (error) {
|
||||
const encryptKey = generateEncryptKey()
|
||||
await fs.promises.writeFile(getEncryptionKeyPath(), encryptKey)
|
||||
const defaultLocation = process.env.SECRETKEY_PATH
|
||||
? path.join(process.env.SECRETKEY_PATH, 'encryption.key')
|
||||
: path.join(getUserHome(), '.flowise', 'encryption.key')
|
||||
await fs.promises.writeFile(defaultLocation, encryptKey)
|
||||
return encryptKey
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user