Merge branch 'main' into bugfix/VM2-Security
# Conflicts: # docker/docker-compose.yml
This commit is contained in:
commit
13622ba0ae
|
|
@ -128,7 +128,7 @@ FLOWISE_PASSWORD=1234
|
|||
|
||||
## 🌱 Env Variables
|
||||
|
||||
Flowise support different environment variables to configure your instance. You can specify the following variables in the `.env` file inside `packages/server` folder.
|
||||
Flowise support different environment variables to configure your instance. You can specify the following variables in the `.env` file inside `packages/server` folder. Read [more](https://docs.flowiseai.com/environment-variables)
|
||||
|
||||
| Variable | Description | Type | Default |
|
||||
| -------------------------- | ---------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------- |
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
PORT=3000
|
||||
DATABASE_PATH=/root/.flowise
|
||||
APIKEY_PATH=/root/.flowise
|
||||
LOG_PATH=/root/.flowise/logs
|
||||
# FLOWISE_USERNAME=user
|
||||
# FLOWISE_PASSWORD=1234
|
||||
# DEBUG=true
|
||||
# DATABASE_PATH=/your_database_path/.flowise
|
||||
# APIKEY_PATH=/your_api_key_path/.flowise
|
||||
# LOG_PATH=/your_log_path/logs
|
||||
# LOG_LEVEL=debug (error | warn | info | verbose | debug)
|
||||
# EXECUTION_MODE=child or main
|
||||
# TOOL_FUNCTION_BUILTIN_DEP=crypto,fs
|
||||
# TOOL_FUNCTION_EXTERNAL_DEP=moment,lodash
|
||||
|
|
@ -9,7 +9,7 @@ Starts Flowise from [DockerHub Image](https://hub.docker.com/repository/docker/f
|
|||
3. Open [http://localhost:3000](http://localhost:3000)
|
||||
4. You can bring the containers down by `docker-compose stop`
|
||||
|
||||
## With Authrorization
|
||||
## 🔒 Authrorization
|
||||
|
||||
1. Create `.env` file and specify the `PORT`, `FLOWISE_USERNAME`, and `FLOWISE_PASSWORD` (refer to `.env.example`)
|
||||
2. Pass `FLOWISE_USERNAME` and `FLOWISE_PASSWORD` to the `docker-compose.yml` file:
|
||||
|
|
@ -22,3 +22,27 @@ Starts Flowise from [DockerHub Image](https://hub.docker.com/repository/docker/f
|
|||
3. `docker-compose up -d`
|
||||
4. Open [http://localhost:3000](http://localhost:3000)
|
||||
5. You can bring the containers down by `docker-compose stop`
|
||||
|
||||
## 🌱 Env Variables
|
||||
|
||||
If you like to persist your data (flows, logs, apikeys), set these variables in the `.env` file inside `docker` folder:
|
||||
|
||||
- DATABASE_PATH=/root/.flowise
|
||||
- APIKEY_PATH=/root/.flowise
|
||||
- LOG_PATH=/root/.flowise/logs
|
||||
|
||||
Flowise also support different environment variables to configure your instance. Read [more](https://docs.flowiseai.com/environment-variables)
|
||||
|
||||
| Variable | Description | Type | Default |
|
||||
| -------------------------- | ---------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------- |
|
||||
| PORT | The HTTP port Flowise runs on | Number | 3000 |
|
||||
| FLOWISE_USERNAME | Username to login | String |
|
||||
| FLOWISE_PASSWORD | Password to login | String |
|
||||
| DEBUG | Print logs onto terminal/console | Boolean |
|
||||
| LOG_PATH | Location where log files are stored | String | `your-path/Flowise/packages/server` |
|
||||
| LOG_LEVEL | Different log levels for loggers to be saved | Enum String: `error`, `info`, `verbose`, `debug` | `info` |
|
||||
| DATABASE_PATH | Location where database is saved | String | `your-home-dir/.flowise` |
|
||||
| APIKEY_PATH | Location where api keys are saved | String | `your-path/Flowise/packages/server` |
|
||||
| EXECUTION_MODE | Whether predictions run in their own process or the main process | Enum String: `child`, `main` | `main` |
|
||||
| TOOL_FUNCTION_BUILTIN_DEP | NodeJS built-in modules to be used for Tool Function | String | |
|
||||
| TOOL_FUNCTION_EXTERNAL_DEP | External modules to be used for Tool Function | String | |
|
||||
|
|
|
|||
|
|
@ -8,13 +8,12 @@ services:
|
|||
- PORT=${PORT}
|
||||
- FLOWISE_USERNAME=${FLOWISE_USERNAME}
|
||||
- FLOWISE_PASSWORD=${FLOWISE_PASSWORD}
|
||||
- DEBUG=${DEBUG}
|
||||
- DATABASE_PATH=${DATABASE_PATH}
|
||||
- APIKEY_PATH=${APIKEY_PATH}
|
||||
- LOG_PATH=${LOG_PATH}
|
||||
- LOG_LEVEL=${LOG_LEVEL}
|
||||
- EXECUTION_MODE=${EXECUTION_MODE}
|
||||
- DEBUG=${DEBUG}
|
||||
- TOOL_FUNCTION_BUILTIN_DEP=${TOOL_FUNCTION_BUILTIN_DEP}
|
||||
- TOOL_FUNCTION_EXTERNAL_DEP=${TOOL_FUNCTION_EXTERNAL_DEP}
|
||||
ports:
|
||||
- '${PORT}:${PORT}'
|
||||
volumes:
|
||||
|
|
|
|||
|
|
@ -65,37 +65,47 @@ class DynamoDb_Memory implements INode {
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const tableName = nodeData.inputs?.tableName as string
|
||||
const partitionKey = nodeData.inputs?.partitionKey as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const region = nodeData.inputs?.region as string
|
||||
const accessKey = nodeData.inputs?.accessKey as string
|
||||
const secretAccessKey = nodeData.inputs?.secretAccessKey as string
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
return initalizeDynamoDB(nodeData, options)
|
||||
}
|
||||
|
||||
const chatId = options.chatId
|
||||
|
||||
const dynamoDb = new DynamoDBChatMessageHistory({
|
||||
tableName,
|
||||
partitionKey,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
config: {
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId: accessKey,
|
||||
secretAccessKey
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const memory = new BufferMemory({
|
||||
memoryKey,
|
||||
chatHistory: dynamoDb,
|
||||
returnMessages: true
|
||||
})
|
||||
return memory
|
||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||
const dynamodbMemory = initalizeDynamoDB(nodeData, options)
|
||||
dynamodbMemory.clear()
|
||||
}
|
||||
}
|
||||
|
||||
const initalizeDynamoDB = (nodeData: INodeData, options: ICommonObject): BufferMemory => {
|
||||
const tableName = nodeData.inputs?.tableName as string
|
||||
const partitionKey = nodeData.inputs?.partitionKey as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const region = nodeData.inputs?.region as string
|
||||
const accessKey = nodeData.inputs?.accessKey as string
|
||||
const secretAccessKey = nodeData.inputs?.secretAccessKey as string
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
|
||||
const chatId = options.chatId
|
||||
|
||||
const dynamoDb = new DynamoDBChatMessageHistory({
|
||||
tableName,
|
||||
partitionKey,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
config: {
|
||||
region,
|
||||
credentials: {
|
||||
accessKeyId: accessKey,
|
||||
secretAccessKey
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const memory = new BufferMemory({
|
||||
memoryKey,
|
||||
chatHistory: dynamoDb,
|
||||
returnMessages: true
|
||||
})
|
||||
return memory
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: DynamoDb_Memory }
|
||||
|
|
|
|||
|
|
@ -64,35 +64,44 @@ class MotorMemory_Memory implements INode {
|
|||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const apiKey = nodeData.inputs?.apiKey as string
|
||||
const clientId = nodeData.inputs?.clientId as string
|
||||
return initalizeMotorhead(nodeData, options)
|
||||
}
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
let obj: MotorheadMemoryInput = {
|
||||
returnMessages: true,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
memoryKey
|
||||
}
|
||||
|
||||
if (baseURL) {
|
||||
obj = {
|
||||
...obj,
|
||||
url: baseURL
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
...obj,
|
||||
apiKey,
|
||||
clientId
|
||||
}
|
||||
}
|
||||
|
||||
return new MotorheadMemory(obj)
|
||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||
const motorhead = initalizeMotorhead(nodeData, options)
|
||||
motorhead.clear()
|
||||
}
|
||||
}
|
||||
|
||||
const initalizeMotorhead = (nodeData: INodeData, options: ICommonObject): MotorheadMemory => {
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const apiKey = nodeData.inputs?.apiKey as string
|
||||
const clientId = nodeData.inputs?.clientId as string
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
let obj: MotorheadMemoryInput = {
|
||||
returnMessages: true,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
memoryKey
|
||||
}
|
||||
|
||||
if (baseURL) {
|
||||
obj = {
|
||||
...obj,
|
||||
url: baseURL
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
...obj,
|
||||
apiKey,
|
||||
clientId
|
||||
}
|
||||
}
|
||||
|
||||
return new MotorheadMemory(obj)
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: MotorMemory_Memory }
|
||||
|
|
|
|||
|
|
@ -56,31 +56,40 @@ class RedisBackedChatMemory_Memory implements INode {
|
|||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const sessionTTL = nodeData.inputs?.sessionTTL as number
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
return initalizeRedis(nodeData, options)
|
||||
}
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
const redisClient = createClient({ url: baseURL })
|
||||
let obj: RedisChatMessageHistoryInput = {
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
client: redisClient
|
||||
}
|
||||
|
||||
if (sessionTTL) {
|
||||
obj = {
|
||||
...obj,
|
||||
sessionTTL
|
||||
}
|
||||
}
|
||||
|
||||
let redisChatMessageHistory = new RedisChatMessageHistory(obj)
|
||||
let redis = new BufferMemory({ memoryKey, chatHistory: redisChatMessageHistory, returnMessages: true })
|
||||
|
||||
return redis
|
||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||
const redis = initalizeRedis(nodeData, options)
|
||||
redis.clear()
|
||||
}
|
||||
}
|
||||
|
||||
const initalizeRedis = (nodeData: INodeData, options: ICommonObject): BufferMemory => {
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const sessionTTL = nodeData.inputs?.sessionTTL as number
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
const redisClient = createClient({ url: baseURL })
|
||||
let obj: RedisChatMessageHistoryInput = {
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
client: redisClient
|
||||
}
|
||||
|
||||
if (sessionTTL) {
|
||||
obj = {
|
||||
...obj,
|
||||
sessionTTL
|
||||
}
|
||||
}
|
||||
|
||||
let redisChatMessageHistory = new RedisChatMessageHistory(obj)
|
||||
let redis = new BufferMemory({ memoryKey, chatHistory: redisChatMessageHistory, returnMessages: true })
|
||||
|
||||
return redis
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: RedisBackedChatMemory_Memory }
|
||||
|
|
|
|||
|
|
@ -104,31 +104,11 @@ class ZepMemory_Memory implements INode {
|
|||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const aiPrefix = nodeData.inputs?.aiPrefix as string
|
||||
const humanPrefix = nodeData.inputs?.humanPrefix as string
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
const inputKey = nodeData.inputs?.inputKey as string
|
||||
const autoSummaryTemplate = nodeData.inputs?.autoSummaryTemplate as string
|
||||
const autoSummary = nodeData.inputs?.autoSummary as boolean
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const apiKey = nodeData.inputs?.apiKey as string
|
||||
const k = nodeData.inputs?.k as string
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
const obj: ZepMemoryInput = {
|
||||
baseURL,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
aiPrefix,
|
||||
humanPrefix,
|
||||
returnMessages: true,
|
||||
memoryKey,
|
||||
inputKey
|
||||
}
|
||||
if (apiKey) obj.apiKey = apiKey
|
||||
|
||||
let zep = new ZepMemory(obj)
|
||||
let zep = initalizeZep(nodeData, options)
|
||||
|
||||
// hack to support summary
|
||||
let tmpFunc = zep.loadMemoryVariables
|
||||
|
|
@ -153,6 +133,37 @@ class ZepMemory_Memory implements INode {
|
|||
}
|
||||
return zep
|
||||
}
|
||||
|
||||
async clearSessionMemory(nodeData: INodeData, options: ICommonObject): Promise<void> {
|
||||
const zep = initalizeZep(nodeData, options)
|
||||
zep.clear()
|
||||
}
|
||||
}
|
||||
|
||||
const initalizeZep = (nodeData: INodeData, options: ICommonObject) => {
|
||||
const baseURL = nodeData.inputs?.baseURL as string
|
||||
const aiPrefix = nodeData.inputs?.aiPrefix as string
|
||||
const humanPrefix = nodeData.inputs?.humanPrefix as string
|
||||
const memoryKey = nodeData.inputs?.memoryKey as string
|
||||
const inputKey = nodeData.inputs?.inputKey as string
|
||||
|
||||
const sessionId = nodeData.inputs?.sessionId as string
|
||||
const apiKey = nodeData.inputs?.apiKey as string
|
||||
|
||||
const chatId = options?.chatId as string
|
||||
|
||||
const obj: ZepMemoryInput = {
|
||||
baseURL,
|
||||
sessionId: sessionId ? sessionId : chatId,
|
||||
aiPrefix,
|
||||
humanPrefix,
|
||||
returnMessages: true,
|
||||
memoryKey,
|
||||
inputKey
|
||||
}
|
||||
if (apiKey) obj.apiKey = apiKey
|
||||
|
||||
return new ZepMemory(obj)
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: ZepMemory_Memory }
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ export interface INode extends INodeProperties {
|
|||
}
|
||||
init?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<any>
|
||||
run?(nodeData: INodeData, input: string, options?: ICommonObject): Promise<string | ICommonObject>
|
||||
clearSessionMemory?(nodeData: INodeData, options?: ICommonObject): Promise<void>
|
||||
}
|
||||
|
||||
export interface INodeData extends INodeProperties {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ PORT=3000
|
|||
# DEBUG=true
|
||||
# DATABASE_PATH=/your_database_path/.flowise
|
||||
# APIKEY_PATH=/your_api_key_path/.flowise
|
||||
# LOG_PATH=/your_log_path/logs
|
||||
# LOG_PATH=/your_log_path/.flowise/logs
|
||||
# LOG_LEVEL=debug (error | warn | info | verbose | debug)
|
||||
# EXECUTION_MODE=main (child | main)
|
||||
# TOOL_FUNCTION_BUILTIN_DEP=crypto,fs
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ FLOWISE_PASSWORD=1234
|
|||
|
||||
## 🌱 Env Variables
|
||||
|
||||
Flowise support different environment variables to configure your instance. You can specify the following variables in the `.env` file inside `packages/server` folder.
|
||||
Flowise support different environment variables to configure your instance. You can specify the following variables in the `.env` file inside `packages/server` folder. Read [more](https://docs.flowiseai.com/environment-variables)
|
||||
|
||||
| Variable | Description | Type | Default |
|
||||
| -------------------------- | ---------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------- |
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ import {
|
|||
isFlowValidForStream,
|
||||
isVectorStoreFaiss,
|
||||
databaseEntities,
|
||||
getApiKey
|
||||
getApiKey,
|
||||
clearSessionMemory
|
||||
} from './utils'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { getDataSource } from './DataSource'
|
||||
|
|
@ -331,6 +332,19 @@ export class App {
|
|||
|
||||
// Delete all chatmessages from chatflowid
|
||||
this.app.delete('/api/v1/chatmessage/:id', async (req: Request, res: Response) => {
|
||||
const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: req.params.id
|
||||
})
|
||||
if (!chatflow) {
|
||||
res.status(404).send(`Chatflow ${req.params.id} not found`)
|
||||
return
|
||||
}
|
||||
const flowData = chatflow.flowData
|
||||
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
|
||||
const nodes = parsedFlowData.nodes
|
||||
let chatId = await getChatId(chatflow.id)
|
||||
if (!chatId) chatId = chatflow.id
|
||||
clearSessionMemory(nodes, this.nodesPool.componentNodes, chatId, req.query.sessionId as string)
|
||||
const results = await this.AppDataSource.getRepository(ChatMessage).delete({ chatflowid: req.params.id })
|
||||
return res.json(results)
|
||||
})
|
||||
|
|
@ -673,7 +687,7 @@ export class App {
|
|||
if (!chatflow) return res.status(404).send(`Chatflow ${chatflowid} not found`)
|
||||
|
||||
let chatId = await getChatId(chatflow.id)
|
||||
if (!chatId) chatId = Date.now().toString()
|
||||
if (!chatId) chatId = chatflowid
|
||||
|
||||
if (!isInternal) {
|
||||
await this.validateKey(req, res, chatflow)
|
||||
|
|
|
|||
|
|
@ -273,6 +273,29 @@ export const buildLangchain = async (
|
|||
return flowNodes
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear memory
|
||||
* @param {IReactFlowNode[]} reactFlowNodes
|
||||
* @param {IComponentNodes} componentNodes
|
||||
* @param {string} chatId
|
||||
* @param {string} sessionId
|
||||
*/
|
||||
export const clearSessionMemory = async (
|
||||
reactFlowNodes: IReactFlowNode[],
|
||||
componentNodes: IComponentNodes,
|
||||
chatId: string,
|
||||
sessionId?: string
|
||||
) => {
|
||||
for (const node of reactFlowNodes) {
|
||||
if (node.data.category !== 'Memory') continue
|
||||
const nodeInstanceFilePath = componentNodes[node.data.name].filePath as string
|
||||
const nodeModule = await import(nodeInstanceFilePath)
|
||||
const newNodeInstance = new nodeModule.nodeClass()
|
||||
if (sessionId && node.data.inputs) node.data.inputs.sessionId = sessionId
|
||||
if (newNodeInstance.clearSessionMemory) await newNodeInstance?.clearSessionMemory(node.data, { chatId })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variable value from outputResponses.output
|
||||
* @param {string} paramValue
|
||||
|
|
|
|||
Loading…
Reference in New Issue