add chatpools data
This commit is contained in:
parent
94e71b22e2
commit
df7a3995cd
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue