mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 13:00:56 +03:00
Merge branch 'main' into FEATURE/Vision
This commit is contained in:
@@ -18,6 +18,7 @@ export default class Start extends Command {
|
||||
static flags = {
|
||||
FLOWISE_USERNAME: Flags.string(),
|
||||
FLOWISE_PASSWORD: Flags.string(),
|
||||
FLOWISE_FILE_SIZE_LIMIT: Flags.string(),
|
||||
PORT: Flags.string(),
|
||||
CORS_ORIGINS: Flags.string(),
|
||||
IFRAME_ORIGINS: Flags.string(),
|
||||
@@ -95,6 +96,9 @@ export default class Start extends Command {
|
||||
// Storage
|
||||
if (flags.BLOB_STORAGE_PATH) process.env.BLOB_STORAGE_PATH = flags.BLOB_STORAGE_PATH
|
||||
|
||||
//API Configuration
|
||||
if (flags.FLOWISE_FILE_SIZE_LIMIT) process.env.FLOWISE_FILE_SIZE_LIMIT = flags.FLOWISE_FILE_SIZE_LIMIT
|
||||
|
||||
// Credentials
|
||||
if (flags.SECRETKEY_PATH) process.env.SECRETKEY_PATH = flags.SECRETKEY_PATH
|
||||
if (flags.FLOWISE_SECRETKEY_OVERWRITE) process.env.FLOWISE_SECRETKEY_OVERWRITE = flags.FLOWISE_SECRETKEY_OVERWRITE
|
||||
|
||||
@@ -133,8 +133,9 @@ export class App {
|
||||
|
||||
async config(socketIO?: Server) {
|
||||
// Limit is needed to allow sending/receiving base64 encoded string
|
||||
this.app.use(express.json({ limit: '50mb' }))
|
||||
this.app.use(express.urlencoded({ limit: '50mb', extended: true }))
|
||||
const flowise_file_size_limit = process.env.FLOWISE_FILE_SIZE_LIMIT ?? '50mb'
|
||||
this.app.use(express.json({ limit: flowise_file_size_limit }))
|
||||
this.app.use(express.urlencoded({ limit: flowise_file_size_limit, extended: true }))
|
||||
|
||||
if (process.env.NUMBER_OF_PROXIES && parseInt(process.env.NUMBER_OF_PROXIES) > 0)
|
||||
this.app.set('trust proxy', parseInt(process.env.NUMBER_OF_PROXIES))
|
||||
@@ -199,7 +200,7 @@ export class App {
|
||||
this.app.get('/api/v1/ip', (request, response) => {
|
||||
response.send({
|
||||
ip: request.ip,
|
||||
msg: 'See the returned IP address in the response. If it matches your current IP address ( which you can get by going to http://ip.nfriedly.com/ or https://api.ipify.org/ ), then the number of proxies is correct and the rate limiter should now work correctly. If not, increase the number of proxies by 1 until the IP address matches your own. Visit https://docs.flowiseai.com/deployment#rate-limit-setup-guide for more information.'
|
||||
msg: 'Check returned IP address in the response. If it matches your current IP address ( which you can get by going to http://ip.nfriedly.com/ or https://api.ipify.org/ ), then the number of proxies is correct and the rate limiter should now work correctly. If not, increase the number of proxies by 1 and restart Cloud-Hosted Flowise until the IP address matches your own. Visit https://docs.flowiseai.com/configuration/rate-limit#cloud-hosted-rate-limit-setup-guide for more information.'
|
||||
})
|
||||
})
|
||||
|
||||
@@ -509,7 +510,12 @@ export class App {
|
||||
const isEndingNode = endingNodeData?.outputs?.output === 'EndingNode'
|
||||
|
||||
if (!isEndingNode) {
|
||||
if (endingNodeData && endingNodeData.category !== 'Chains' && endingNodeData.category !== 'Agents') {
|
||||
if (
|
||||
endingNodeData &&
|
||||
endingNodeData.category !== 'Chains' &&
|
||||
endingNodeData.category !== 'Agents' &&
|
||||
endingNodeData.category !== 'Engine'
|
||||
) {
|
||||
return res.status(500).send(`Ending node must be either a Chain or Agent`)
|
||||
}
|
||||
}
|
||||
@@ -542,6 +548,7 @@ export class App {
|
||||
const chatId = req.query?.chatId as string | undefined
|
||||
const memoryType = req.query?.memoryType as string | undefined
|
||||
const sessionId = req.query?.sessionId as string | undefined
|
||||
const messageId = req.query?.messageId as string | undefined
|
||||
const startDate = req.query?.startDate as string | undefined
|
||||
const endDate = req.query?.endDate as string | undefined
|
||||
let chatTypeFilter = req.query?.chatType as chatType | undefined
|
||||
@@ -569,7 +576,8 @@ export class App {
|
||||
memoryType,
|
||||
sessionId,
|
||||
startDate,
|
||||
endDate
|
||||
endDate,
|
||||
messageId
|
||||
)
|
||||
return res.json(chatmessages)
|
||||
})
|
||||
@@ -1224,8 +1232,14 @@ export class App {
|
||||
this.app.get('/api/v1/fetch-links', async (req: Request, res: Response) => {
|
||||
const url = decodeURIComponent(req.query.url as string)
|
||||
const relativeLinksMethod = req.query.relativeLinksMethod as string
|
||||
if (!relativeLinksMethod) {
|
||||
return res.status(500).send('Please choose a Relative Links Method in Additional Parameters.')
|
||||
}
|
||||
|
||||
const limit = parseInt(req.query.limit as string)
|
||||
if (process.env.DEBUG === 'true') console.info(`Start ${relativeLinksMethod}`)
|
||||
const links: string[] = relativeLinksMethod === 'webCrawl' ? await webCrawl(url, 0) : await xmlScrape(url, 0)
|
||||
const links: string[] = relativeLinksMethod === 'webCrawl' ? await webCrawl(url, limit) : await xmlScrape(url, limit)
|
||||
if (process.env.DEBUG === 'true') console.info(`Finish ${relativeLinksMethod}`)
|
||||
|
||||
res.json({ status: 'OK', links })
|
||||
})
|
||||
@@ -1299,50 +1313,52 @@ export class App {
|
||||
// Marketplaces
|
||||
// ----------------------------------------
|
||||
|
||||
// Get all chatflows for marketplaces
|
||||
this.app.get('/api/v1/marketplaces/chatflows', async (req: Request, res: Response) => {
|
||||
const marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'chatflows')
|
||||
const jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
const templates: any[] = []
|
||||
// Get all templates for marketplaces
|
||||
this.app.get('/api/v1/marketplaces/templates', async (req: Request, res: Response) => {
|
||||
let marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'chatflows')
|
||||
let jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
let templates: any[] = []
|
||||
jsonsInDir.forEach((file, index) => {
|
||||
const filePath = path.join(__dirname, '..', 'marketplaces', 'chatflows', file)
|
||||
const fileData = fs.readFileSync(filePath)
|
||||
const fileDataObj = JSON.parse(fileData.toString())
|
||||
const template = {
|
||||
id: index,
|
||||
name: file.split('.json')[0],
|
||||
templateName: file.split('.json')[0],
|
||||
flowData: fileData.toString(),
|
||||
badge: fileDataObj?.badge,
|
||||
framework: fileDataObj?.framework,
|
||||
categories: fileDataObj?.categories,
|
||||
type: 'Chatflow',
|
||||
description: fileDataObj?.description || ''
|
||||
}
|
||||
templates.push(template)
|
||||
})
|
||||
|
||||
marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'tools')
|
||||
jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
jsonsInDir.forEach((file, index) => {
|
||||
const filePath = path.join(__dirname, '..', 'marketplaces', 'tools', file)
|
||||
const fileData = fs.readFileSync(filePath)
|
||||
const fileDataObj = JSON.parse(fileData.toString())
|
||||
const template = {
|
||||
...fileDataObj,
|
||||
id: index,
|
||||
type: 'Tool',
|
||||
framework: fileDataObj?.framework,
|
||||
badge: fileDataObj?.badge,
|
||||
categories: '',
|
||||
templateName: file.split('.json')[0]
|
||||
}
|
||||
templates.push(template)
|
||||
})
|
||||
const FlowiseDocsQnA = templates.find((tmp) => tmp.name === 'Flowise Docs QnA')
|
||||
const FlowiseDocsQnAIndex = templates.findIndex((tmp) => tmp.name === 'Flowise Docs QnA')
|
||||
if (FlowiseDocsQnA && FlowiseDocsQnAIndex > 0) {
|
||||
templates.splice(FlowiseDocsQnAIndex, 1)
|
||||
templates.unshift(FlowiseDocsQnA)
|
||||
}
|
||||
return res.json(templates)
|
||||
})
|
||||
|
||||
// Get all tools for marketplaces
|
||||
this.app.get('/api/v1/marketplaces/tools', async (req: Request, res: Response) => {
|
||||
const marketplaceDir = path.join(__dirname, '..', 'marketplaces', 'tools')
|
||||
const jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
const templates: any[] = []
|
||||
jsonsInDir.forEach((file, index) => {
|
||||
const filePath = path.join(__dirname, '..', 'marketplaces', 'tools', file)
|
||||
const fileData = fs.readFileSync(filePath)
|
||||
const fileDataObj = JSON.parse(fileData.toString())
|
||||
const template = {
|
||||
...fileDataObj,
|
||||
id: index,
|
||||
templateName: file.split('.json')[0]
|
||||
}
|
||||
templates.push(template)
|
||||
})
|
||||
return res.json(templates)
|
||||
return res.json(templates.sort((a, b) => a.templateName.localeCompare(b.templateName)))
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
@@ -1573,7 +1589,8 @@ export class App {
|
||||
memoryType?: string,
|
||||
sessionId?: string,
|
||||
startDate?: string,
|
||||
endDate?: string
|
||||
endDate?: string,
|
||||
messageId?: string
|
||||
): Promise<ChatMessage[]> {
|
||||
let fromDate
|
||||
if (startDate) fromDate = new Date(startDate)
|
||||
@@ -1587,8 +1604,9 @@ export class App {
|
||||
chatType,
|
||||
chatId,
|
||||
memoryType: memoryType ?? (chatId ? IsNull() : undefined),
|
||||
sessionId: sessionId ?? (chatId ? IsNull() : undefined),
|
||||
createdDate: toDate && fromDate ? Between(fromDate, toDate) : undefined
|
||||
sessionId: sessionId ?? undefined,
|
||||
createdDate: toDate && fromDate ? Between(fromDate, toDate) : undefined,
|
||||
id: messageId ?? undefined
|
||||
},
|
||||
order: {
|
||||
createdDate: sortOrder === 'DESC' ? 'DESC' : 'ASC'
|
||||
@@ -1888,7 +1906,12 @@ export class App {
|
||||
const isEndingNode = endingNodeData?.outputs?.output === 'EndingNode'
|
||||
|
||||
if (!isEndingNode) {
|
||||
if (endingNodeData && endingNodeData.category !== 'Chains' && endingNodeData.category !== 'Agents') {
|
||||
if (
|
||||
endingNodeData &&
|
||||
endingNodeData.category !== 'Chains' &&
|
||||
endingNodeData.category !== 'Agents' &&
|
||||
endingNodeData.category !== 'Engine'
|
||||
) {
|
||||
return res.status(500).send(`Ending node must be either a Chain or Agent`)
|
||||
}
|
||||
|
||||
|
||||
@@ -821,7 +821,16 @@ export const findAvailableConfigs = (reactFlowNodes: IReactFlowNode[], component
|
||||
*/
|
||||
export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNodeData: INodeData) => {
|
||||
const streamAvailableLLMs = {
|
||||
'Chat Models': ['azureChatOpenAI', 'chatOpenAI', 'chatAnthropic', 'chatOllama', 'awsChatBedrock', 'chatMistralAI'],
|
||||
'Chat Models': [
|
||||
'azureChatOpenAI',
|
||||
'chatOpenAI',
|
||||
'chatOpenAI_LlamaIndex',
|
||||
'chatAnthropic',
|
||||
'chatAnthropic_LlamaIndex',
|
||||
'chatOllama',
|
||||
'awsChatBedrock',
|
||||
'chatMistralAI'
|
||||
],
|
||||
LLMs: ['azureOpenAI', 'openAI', 'ollama']
|
||||
}
|
||||
|
||||
@@ -844,6 +853,9 @@ export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNod
|
||||
// Agent that are available to stream
|
||||
const whitelistAgents = ['openAIFunctionAgent', 'csvAgent', 'airtableAgent', 'conversationalRetrievalAgent']
|
||||
isValidChainOrAgent = whitelistAgents.includes(endingNodeData.name)
|
||||
} else if (endingNodeData.category === 'Engine') {
|
||||
const whitelistEngine = ['contextChatEngine', 'simpleChatEngine', 'queryEngine', 'subQuestionQueryEngine']
|
||||
isValidChainOrAgent = whitelistEngine.includes(endingNodeData.name)
|
||||
}
|
||||
|
||||
// If no output parser, flow is available to stream
|
||||
|
||||
Reference in New Issue
Block a user