add chatpools data

This commit is contained in:
Henry 2023-04-19 23:31:41 +01:00
parent 94e71b22e2
commit df7a3995cd
4 changed files with 48 additions and 42 deletions

View File

@ -1,4 +1,4 @@
import { IActiveChatflows, INodeData } from './Interface' import { IActiveChatflows, INodeData, IReactFlowNode } from './Interface'
/** /**
* This pool is to keep track of active chatflow pools * This pool is to keep track of active chatflow pools
@ -11,9 +11,11 @@ export class ChatflowPool {
* Add to the pool * Add to the pool
* @param {string} chatflowid * @param {string} chatflowid
* @param {INodeData} endingNodeData * @param {INodeData} endingNodeData
* @param {IReactFlowNode[]} startingNodes
*/ */
add(chatflowid: string, endingNodeData: INodeData) { add(chatflowid: string, endingNodeData: INodeData, startingNodes: IReactFlowNode[]) {
this.activeChatflows[chatflowid] = { this.activeChatflows[chatflowid] = {
startingNodes,
endingNodeData, endingNodeData,
inSync: true inSync: true
} }

View File

@ -117,6 +117,7 @@ export interface IncomingInput {
export interface IActiveChatflows { export interface IActiveChatflows {
[key: string]: { [key: string]: {
startingNodes: IReactFlowNode[]
endingNodeData: INodeData endingNodeData: INodeData
inSync: boolean inSync: boolean
} }

View File

@ -12,7 +12,7 @@ import {
getEndingNode, getEndingNode,
constructGraphs, constructGraphs,
resolveVariables, resolveVariables,
checkStartNodeDependOnInput isStartNodeDependOnInput
} from './utils' } from './utils'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { getDataSource } from './DataSource' import { getDataSource } from './DataSource'
@ -203,39 +203,6 @@ export class App {
let nodeToExecuteData: INodeData let nodeToExecuteData: INodeData
/*** Get chatflows and prepare data ***/
const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
id: chatflowid
})
if (!chatflow) return res.status(404).send(`Chatflow ${chatflowid} not found`)
const flowData = chatflow.flowData
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
const nodes = parsedFlowData.nodes
const edges = parsedFlowData.edges
/*** Get Ending Node with Directed Graph ***/
const { graph, nodeDependencies } = constructGraphs(nodes, edges)
const directedGraph = graph
const endingNodeId = getEndingNode(nodeDependencies, directedGraph)
if (!endingNodeId) return res.status(500).send(`Ending node must be either a Chain or Agent`)
const endingNodeData = nodes.find((nd) => nd.id === endingNodeId)?.data
if (!endingNodeData) return res.status(500).send(`Ending node must be either a Chain or Agent`)
if (endingNodeData.outputs && !Object.values(endingNodeData.outputs).includes(endingNodeData.name)) {
return res
.status(500)
.send(
`Output of ${endingNodeData.label} (${endingNodeData.id}) must be ${endingNodeData.label}, can't be an Output Prediction`
)
}
/*** Get Starting Nodes with Non-Directed Graph ***/
const constructedObj = constructGraphs(nodes, edges, true)
const nonDirectedGraph = constructedObj.graph
const { startingNodeIds, depthQueue } = getStartingNodes(nonDirectedGraph, endingNodeId)
/* Check if: /* Check if:
* - Node Data already exists in pool * - Node Data already exists in pool
* - Still in sync (i.e the flow has not been modified since) * - Still in sync (i.e the flow has not been modified since)
@ -244,10 +211,47 @@ export class App {
if ( if (
Object.prototype.hasOwnProperty.call(this.chatflowPool.activeChatflows, chatflowid) && Object.prototype.hasOwnProperty.call(this.chatflowPool.activeChatflows, chatflowid) &&
this.chatflowPool.activeChatflows[chatflowid].inSync && this.chatflowPool.activeChatflows[chatflowid].inSync &&
!checkStartNodeDependOnInput(nodes, startingNodeIds) !isStartNodeDependOnInput(this.chatflowPool.activeChatflows[chatflowid].startingNodes)
) { ) {
nodeToExecuteData = this.chatflowPool.activeChatflows[chatflowid].endingNodeData nodeToExecuteData = this.chatflowPool.activeChatflows[chatflowid].endingNodeData
} else { } else {
/*** Get chatflows and prepare data ***/
const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
id: chatflowid
})
if (!chatflow) return res.status(404).send(`Chatflow ${chatflowid} not found`)
const flowData = chatflow.flowData
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
const nodes = parsedFlowData.nodes
const edges = parsedFlowData.edges
/*** Get Ending Node with Directed Graph ***/
const { graph, nodeDependencies } = constructGraphs(nodes, edges)
const directedGraph = graph
const endingNodeId = getEndingNode(nodeDependencies, directedGraph)
if (!endingNodeId) return res.status(500).send(`Ending node must be either a Chain or Agent`)
const endingNodeData = nodes.find((nd) => nd.id === endingNodeId)?.data
if (!endingNodeData) return res.status(500).send(`Ending node must be either a Chain or Agent`)
if (
endingNodeData.outputs &&
Object.keys(endingNodeData.outputs).length &&
!Object.values(endingNodeData.outputs).includes(endingNodeData.name)
) {
return res
.status(500)
.send(
`Output of ${endingNodeData.label} (${endingNodeData.id}) must be ${endingNodeData.label}, can't be an Output Prediction`
)
}
/*** Get Starting Nodes with Non-Directed Graph ***/
const constructedObj = constructGraphs(nodes, edges, true)
const nonDirectedGraph = constructedObj.graph
const { startingNodeIds, depthQueue } = getStartingNodes(nonDirectedGraph, endingNodeId)
/*** BFS to traverse from Starting Nodes to Ending Node ***/ /*** BFS to traverse from Starting Nodes to Ending Node ***/
const reactFlowNodes = await buildLangchain( const reactFlowNodes = await buildLangchain(
startingNodeIds, startingNodeIds,
@ -264,7 +268,8 @@ export class App {
const reactFlowNodeData: INodeData = resolveVariables(nodeToExecute.data, reactFlowNodes, incomingInput.question) const reactFlowNodeData: INodeData = resolveVariables(nodeToExecute.data, reactFlowNodes, incomingInput.question)
nodeToExecuteData = reactFlowNodeData nodeToExecuteData = reactFlowNodeData
this.chatflowPool.add(chatflowid, nodeToExecuteData) const startingNodes = nodes.filter((nd) => startingNodeIds.includes(nd.id))
this.chatflowPool.add(chatflowid, nodeToExecuteData, startingNodes)
} }
const nodeInstanceFilePath = this.nodesPool.componentNodes[nodeToExecuteData.name].filePath as string const nodeInstanceFilePath = this.nodesPool.componentNodes[nodeToExecuteData.name].filePath as string

View File

@ -350,12 +350,10 @@ export const resolveVariables = (reactFlowNodeData: INodeData, reactFlowNodes: I
/** /**
* Rebuild flow if LLMChain has dependency on other chains * Rebuild flow if LLMChain has dependency on other chains
* User Question => Prompt_0 => LLMChain_0 => Prompt-1 => LLMChain_1 * User Question => Prompt_0 => LLMChain_0 => Prompt-1 => LLMChain_1
* @param {IReactFlowNode[]} nodes * @param {IReactFlowNode[]} startingNodes
* @param {string[]} startingNodeIds
* @returns {boolean} * @returns {boolean}
*/ */
export const checkStartNodeDependOnInput = (nodes: IReactFlowNode[], startingNodeIds: string[]) => { export const isStartNodeDependOnInput = (startingNodes: IReactFlowNode[]): boolean => {
const startingNodes = nodes.filter((nd) => startingNodeIds.includes(nd.id) && nd.id.toLowerCase().includes('prompttemplate'))
for (const node of startingNodes) { for (const node of startingNodes) {
for (const inputName in node.data.inputs) { for (const inputName in node.data.inputs) {
const inputVariables = getInputVariables(node.data.inputs[inputName]) const inputVariables = getInputVariables(node.data.inputs[inputName])