mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 13:00:56 +03:00
Merge branch 'main' into BUGFIX/XSS
# Conflicts: # packages/server/src/index.ts
This commit is contained in:
@@ -205,7 +205,7 @@
|
||||
"data": {
|
||||
"id": "ZepMemory_0",
|
||||
"label": "Zep Memory",
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"name": "ZepMemory",
|
||||
"type": "ZepMemory",
|
||||
"baseClasses": ["ZepMemory", "BaseChatMemory", "BaseMemory"],
|
||||
@@ -228,13 +228,6 @@
|
||||
"default": "http://127.0.0.1:8000",
|
||||
"id": "ZepMemory_0-input-baseURL-string"
|
||||
},
|
||||
{
|
||||
"label": "Auto Summary",
|
||||
"name": "autoSummary",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"id": "ZepMemory_0-input-autoSummary-boolean"
|
||||
},
|
||||
{
|
||||
"label": "Session Id",
|
||||
"name": "sessionId",
|
||||
@@ -251,17 +244,10 @@
|
||||
"type": "number",
|
||||
"default": "10",
|
||||
"step": 1,
|
||||
"additionalParams": true,
|
||||
"description": "Window of size k to surface the last k back-and-forths to use as memory.",
|
||||
"id": "ZepMemory_0-input-k-number"
|
||||
},
|
||||
{
|
||||
"label": "Auto Summary Template",
|
||||
"name": "autoSummaryTemplate",
|
||||
"type": "string",
|
||||
"default": "This is the summary of the following conversation:\n{summary}",
|
||||
"additionalParams": true,
|
||||
"id": "ZepMemory_0-input-autoSummaryTemplate-string"
|
||||
},
|
||||
{
|
||||
"label": "AI Prefix",
|
||||
"name": "aiPrefix",
|
||||
@@ -306,10 +292,8 @@
|
||||
"inputAnchors": [],
|
||||
"inputs": {
|
||||
"baseURL": "http://127.0.0.1:8000",
|
||||
"autoSummary": true,
|
||||
"sessionId": "",
|
||||
"k": "10",
|
||||
"autoSummaryTemplate": "This is the summary of the following conversation:\n{summary}",
|
||||
"aiPrefix": "ai",
|
||||
"humanPrefix": "human",
|
||||
"memoryKey": "chat_history",
|
||||
|
||||
@@ -59,6 +59,9 @@ import { ICommonObject, IMessage, INodeOptionsValue } from 'flowise-components'
|
||||
import { createRateLimiter, getRateLimiter, initializeRateLimiter } from './utils/rateLimit'
|
||||
import { addAPIKey, compareKeys, deleteAPIKey, getApiKey, getAPIKeys, updateAPIKey } from './utils/apiKey'
|
||||
import { sanitizeMiddleware } from './utils/XSS'
|
||||
import axios from 'axios'
|
||||
import { Client } from 'langchainhub'
|
||||
import { parsePrompt } from './utils/hub'
|
||||
|
||||
export class App {
|
||||
app: express.Application
|
||||
@@ -1049,6 +1052,56 @@ export class App {
|
||||
await this.buildChatflow(req, res, undefined, true, true)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Prompt from Hub
|
||||
// ----------------------------------------
|
||||
this.app.post('/api/v1/load-prompt', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const credential = await this.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: req.body.credential
|
||||
})
|
||||
|
||||
if (!credential) return res.status(404).json({ error: `Credential ${req.body.credential} not found` })
|
||||
|
||||
// Decrypt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData, credential.credentialName, undefined)
|
||||
let hub = new Client({ apiKey: decryptedCredentialData.langsmithApiKey, apiUrl: decryptedCredentialData.langsmithEndpoint })
|
||||
const prompt = await hub.pull(req.body.promptName)
|
||||
const templates = parsePrompt(prompt)
|
||||
|
||||
return res.json({ status: 'OK', prompt: req.body.promptName, templates: templates })
|
||||
} catch (e: any) {
|
||||
return res.json({ status: 'ERROR', prompt: req.body.promptName, error: e?.message })
|
||||
}
|
||||
})
|
||||
|
||||
this.app.post('/api/v1/prompts-list', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const credential = await this.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: req.body.credential
|
||||
})
|
||||
|
||||
if (!credential) return res.status(404).json({ error: `Credential ${req.body.credential} not found` })
|
||||
// Decrypt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData, credential.credentialName, undefined)
|
||||
|
||||
const headers = {}
|
||||
// @ts-ignore
|
||||
headers['x-api-key'] = decryptedCredentialData.langsmithApiKey
|
||||
|
||||
const tags = req.body.tags ? `tags=${req.body.tags}` : ''
|
||||
// Default to 100, TODO: add pagination and use offset & limit
|
||||
const url = `https://web.hub.langchain.com/repos/?limit=100&${tags}has_commits=true&sort_field=num_likes&sort_direction=desc&is_archived=false`
|
||||
axios.get(url, headers).then((response) => {
|
||||
if (response.data.repos) {
|
||||
return res.json({ status: 'OK', repos: response.data.repos })
|
||||
}
|
||||
})
|
||||
} catch (e: any) {
|
||||
return res.json({ status: 'ERROR', repos: [] })
|
||||
}
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Prediction
|
||||
// ----------------------------------------
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
export function parsePrompt(prompt: string): any[] {
|
||||
const promptObj = JSON.parse(prompt)
|
||||
let response = []
|
||||
if (promptObj.kwargs.messages) {
|
||||
promptObj.kwargs.messages.forEach((message: any) => {
|
||||
let messageType = message.id.includes('SystemMessagePromptTemplate')
|
||||
? 'systemMessagePrompt'
|
||||
: message.id.includes('HumanMessagePromptTemplate')
|
||||
? 'humanMessagePrompt'
|
||||
: message.id.includes('AIMessagePromptTemplate')
|
||||
? 'aiMessagePrompt'
|
||||
: 'template'
|
||||
let messageTypeDisplay = message.id.includes('SystemMessagePromptTemplate')
|
||||
? 'System Message'
|
||||
: message.id.includes('HumanMessagePromptTemplate')
|
||||
? 'Human Message'
|
||||
: message.id.includes('AIMessagePromptTemplate')
|
||||
? 'AI Message'
|
||||
: 'Message'
|
||||
let template = message.kwargs.prompt.kwargs.template
|
||||
response.push({
|
||||
type: messageType,
|
||||
typeDisplay: messageTypeDisplay,
|
||||
template: template
|
||||
})
|
||||
})
|
||||
} else if (promptObj.kwargs.template) {
|
||||
let template = promptObj.kwargs.template
|
||||
response.push({
|
||||
type: 'template',
|
||||
typeDisplay: 'Prompt',
|
||||
template: template
|
||||
})
|
||||
}
|
||||
return response
|
||||
}
|
||||
@@ -558,9 +558,20 @@ export const isStartNodeDependOnInput = (startingNodes: IReactFlowNode[], nodes:
|
||||
if (inputVariables.length > 0) return true
|
||||
}
|
||||
}
|
||||
const whitelistNodeNames = ['vectorStoreToDocument', 'autoGPT']
|
||||
const whitelistNodeNames = ['vectorStoreToDocument', 'autoGPT', 'chatPromptTemplate', 'promptTemplate'] //If these nodes are found, chatflow cannot be reused
|
||||
for (const node of nodes) {
|
||||
if (whitelistNodeNames.includes(node.data.name)) return true
|
||||
if (node.data.name === 'chatPromptTemplate' || node.data.name === 'promptTemplate') {
|
||||
let promptValues: ICommonObject = {}
|
||||
const promptValuesRaw = node.data.inputs?.promptValues
|
||||
if (promptValuesRaw) {
|
||||
try {
|
||||
promptValues = typeof promptValuesRaw === 'object' ? promptValuesRaw : JSON.parse(promptValuesRaw)
|
||||
} catch (exception) {
|
||||
console.error(exception)
|
||||
}
|
||||
}
|
||||
if (getAllValuesFromJson(promptValues).includes(`{{${QUESTION_VAR_PREFIX}}}`)) return true
|
||||
} else if (whitelistNodeNames.includes(node.data.name)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -913,3 +924,31 @@ export const replaceChatHistory = async (
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values from a JSON object
|
||||
* @param {any} obj
|
||||
* @returns {any[]}
|
||||
*/
|
||||
export const getAllValuesFromJson = (obj: any): any[] => {
|
||||
const values: any[] = []
|
||||
|
||||
function extractValues(data: any) {
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
if (Array.isArray(data)) {
|
||||
for (const item of data) {
|
||||
extractValues(item)
|
||||
}
|
||||
} else {
|
||||
for (const key in data) {
|
||||
extractValues(data[key])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
values.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
extractValues(obj)
|
||||
return values
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user