Merge pull request #908 from FlowiseAI/feature/Analytic
Feature/Add analytic
This commit is contained in:
commit
3d35536de5
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { INodeParams, INodeCredential } from '../src/Interface'
|
||||||
|
|
||||||
|
class LangfuseApi implements INodeCredential {
|
||||||
|
label: string
|
||||||
|
name: string
|
||||||
|
version: number
|
||||||
|
description: string
|
||||||
|
inputs: INodeParams[]
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.label = 'Langfuse API'
|
||||||
|
this.name = 'langfuseApi'
|
||||||
|
this.version = 1.0
|
||||||
|
this.description =
|
||||||
|
'Refer to <a target="_blank" href="https://langfuse.com/docs/get-started/">official guide</a> on how to get API key on Langfuse'
|
||||||
|
this.inputs = [
|
||||||
|
{
|
||||||
|
label: 'Secret Key',
|
||||||
|
name: 'langFuseSecretKey',
|
||||||
|
type: 'password',
|
||||||
|
placeholder: 'sk-lf-abcdefg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Public Key',
|
||||||
|
name: 'langFusePublicKey',
|
||||||
|
type: 'string',
|
||||||
|
placeholder: 'pk-lf-abcdefg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Endpoint',
|
||||||
|
name: 'langFuseEndpoint',
|
||||||
|
type: 'string',
|
||||||
|
default: 'https://cloud.langfuse.com'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { credClass: LangfuseApi }
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { INodeParams, INodeCredential } from '../src/Interface'
|
||||||
|
|
||||||
|
class LangsmithApi implements INodeCredential {
|
||||||
|
label: string
|
||||||
|
name: string
|
||||||
|
version: number
|
||||||
|
description: string
|
||||||
|
inputs: INodeParams[]
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.label = 'Langsmith API'
|
||||||
|
this.name = 'langsmithApi'
|
||||||
|
this.version = 1.0
|
||||||
|
this.description =
|
||||||
|
'Refer to <a target="_blank" href="https://docs.smith.langchain.com/">official guide</a> on how to get API key on Langsmith'
|
||||||
|
this.inputs = [
|
||||||
|
{
|
||||||
|
label: 'API Key',
|
||||||
|
name: 'langSmithApiKey',
|
||||||
|
type: 'password',
|
||||||
|
placeholder: '<LANGSMITH_API_KEY>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Endpoint',
|
||||||
|
name: 'langSmithEndpoint',
|
||||||
|
type: 'string',
|
||||||
|
default: 'https://api.smith.langchain.com'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { credClass: LangsmithApi }
|
||||||
|
|
@ -4,7 +4,7 @@ import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../
|
||||||
import { LoadPyodide, finalSystemPrompt, systemPrompt } from './core'
|
import { LoadPyodide, finalSystemPrompt, systemPrompt } from './core'
|
||||||
import { LLMChain } from 'langchain/chains'
|
import { LLMChain } from 'langchain/chains'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
class Airtable_Agents implements INode {
|
class Airtable_Agents implements INode {
|
||||||
|
|
@ -102,6 +102,7 @@ class Airtable_Agents implements INode {
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
const pyodide = await LoadPyodide()
|
const pyodide = await LoadPyodide()
|
||||||
|
|
||||||
|
|
@ -141,7 +142,7 @@ json.dumps(my_dict)`
|
||||||
dict: dataframeColDict,
|
dict: dataframeColDict,
|
||||||
question: input
|
question: input
|
||||||
}
|
}
|
||||||
const res = await chain.call(inputs, [loggerHandler])
|
const res = await chain.call(inputs, [loggerHandler, ...callbacks])
|
||||||
pythonCode = res?.text
|
pythonCode = res?.text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,10 +170,10 @@ json.dumps(my_dict)`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const result = await chain.call(inputs, [loggerHandler, handler])
|
const result = await chain.call(inputs, [loggerHandler, handler, ...callbacks])
|
||||||
return result?.text
|
return result?.text
|
||||||
} else {
|
} else {
|
||||||
const result = await chain.call(inputs, [loggerHandler])
|
const result = await chain.call(inputs, [loggerHandler, ...callbacks])
|
||||||
return result?.text
|
return result?.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { getBaseClasses } from '../../../src/utils'
|
||||||
import { LoadPyodide, finalSystemPrompt, systemPrompt } from './core'
|
import { LoadPyodide, finalSystemPrompt, systemPrompt } from './core'
|
||||||
import { LLMChain } from 'langchain/chains'
|
import { LLMChain } from 'langchain/chains'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class CSV_Agents implements INode {
|
class CSV_Agents implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -63,6 +63,7 @@ class CSV_Agents implements INode {
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
let files: string[] = []
|
let files: string[] = []
|
||||||
|
|
||||||
|
|
@ -119,7 +120,7 @@ json.dumps(my_dict)`
|
||||||
dict: dataframeColDict,
|
dict: dataframeColDict,
|
||||||
question: input
|
question: input
|
||||||
}
|
}
|
||||||
const res = await chain.call(inputs, [loggerHandler])
|
const res = await chain.call(inputs, [loggerHandler, ...callbacks])
|
||||||
pythonCode = res?.text
|
pythonCode = res?.text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,10 +150,10 @@ json.dumps(my_dict)`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const result = await chain.call(inputs, [loggerHandler, handler])
|
const result = await chain.call(inputs, [loggerHandler, handler, ...callbacks])
|
||||||
return result?.text
|
return result?.text
|
||||||
} else {
|
} else {
|
||||||
const result = await chain.call(inputs, [loggerHandler])
|
const result = await chain.call(inputs, [loggerHandler, ...callbacks])
|
||||||
return result?.text
|
return result?.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { initializeAgentExecutorWithOptions, AgentExecutor } from 'langchain/age
|
||||||
import { getBaseClasses, mapChatHistory } from '../../../src/utils'
|
import { getBaseClasses, mapChatHistory } from '../../../src/utils'
|
||||||
import { flatten } from 'lodash'
|
import { flatten } from 'lodash'
|
||||||
import { BaseChatMemory } from 'langchain/memory'
|
import { BaseChatMemory } from 'langchain/memory'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
const defaultMessage = `Do your best to answer the questions. Feel free to use any tools available to look up relevant information, only if necessary.`
|
const defaultMessage = `Do your best to answer the questions. Feel free to use any tools available to look up relevant information, only if necessary.`
|
||||||
|
|
||||||
|
|
@ -86,13 +86,14 @@ class ConversationalRetrievalAgent_Agents implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const result = await executor.call({ input }, [loggerHandler, handler])
|
const result = await executor.call({ input }, [loggerHandler, handler, ...callbacks])
|
||||||
return result?.output
|
return result?.output
|
||||||
} else {
|
} else {
|
||||||
const result = await executor.call({ input }, [loggerHandler])
|
const result = await executor.call({ input }, [loggerHandler, ...callbacks])
|
||||||
return result?.output
|
return result?.output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { getBaseClasses, mapChatHistory } from '../../../src/utils'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { flatten } from 'lodash'
|
import { flatten } from 'lodash'
|
||||||
import { BaseChatMemory } from 'langchain/memory'
|
import { BaseChatMemory } from 'langchain/memory'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class OpenAIFunctionAgent_Agents implements INode {
|
class OpenAIFunctionAgent_Agents implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -86,13 +86,14 @@ class OpenAIFunctionAgent_Agents implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const result = await executor.run(input, [loggerHandler, handler])
|
const result = await executor.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
const result = await executor.run(input, [loggerHandler])
|
const result = await executor.run(input, [loggerHandler, ...callbacks])
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { INode, INodeParams } from '../../../src/Interface'
|
||||||
|
|
||||||
|
class LangFuse_Analytic implements INode {
|
||||||
|
label: string
|
||||||
|
name: string
|
||||||
|
version: number
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
icon: string
|
||||||
|
category: string
|
||||||
|
baseClasses: string[]
|
||||||
|
inputs?: INodeParams[]
|
||||||
|
credential: INodeParams
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.label = 'LangFuse'
|
||||||
|
this.name = 'langFuse'
|
||||||
|
this.version = 1.0
|
||||||
|
this.type = 'LangFuse'
|
||||||
|
this.icon = 'langfuse.png'
|
||||||
|
this.category = 'Analytic'
|
||||||
|
this.baseClasses = [this.type]
|
||||||
|
this.inputs = []
|
||||||
|
this.credential = {
|
||||||
|
label: 'Connect Credential',
|
||||||
|
name: 'credential',
|
||||||
|
type: 'credential',
|
||||||
|
credentialNames: ['langfuseApi']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { nodeClass: LangFuse_Analytic }
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { INode, INodeParams } from '../../../src/Interface'
|
||||||
|
|
||||||
|
class LangSmith_Analytic implements INode {
|
||||||
|
label: string
|
||||||
|
name: string
|
||||||
|
version: number
|
||||||
|
description: string
|
||||||
|
type: string
|
||||||
|
icon: string
|
||||||
|
category: string
|
||||||
|
baseClasses: string[]
|
||||||
|
inputs?: INodeParams[]
|
||||||
|
credential: INodeParams
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.label = 'LangSmith'
|
||||||
|
this.name = 'langSmith'
|
||||||
|
this.version = 1.0
|
||||||
|
this.type = 'LangSmith'
|
||||||
|
this.icon = 'langchain.png'
|
||||||
|
this.category = 'Analytic'
|
||||||
|
this.baseClasses = [this.type]
|
||||||
|
this.inputs = []
|
||||||
|
this.credential = {
|
||||||
|
label: 'Connect Credential',
|
||||||
|
name: 'credential',
|
||||||
|
type: 'credential',
|
||||||
|
credentialNames: ['langsmithApi']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { nodeClass: LangSmith_Analytic }
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -3,7 +3,7 @@ import { APIChain } from 'langchain/chains'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { getBaseClasses } from '../../../src/utils'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { PromptTemplate } from 'langchain/prompts'
|
import { PromptTemplate } from 'langchain/prompts'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
export const API_URL_RAW_PROMPT_TEMPLATE = `You are given the below API Documentation:
|
export const API_URL_RAW_PROMPT_TEMPLATE = `You are given the below API Documentation:
|
||||||
{api_docs}
|
{api_docs}
|
||||||
|
|
@ -99,13 +99,14 @@ class GETApiChain_Chains implements INode {
|
||||||
|
|
||||||
const chain = await getAPIChain(apiDocs, model, headers, urlPrompt, ansPrompt)
|
const chain = await getAPIChain(apiDocs, model, headers, urlPrompt, ansPrompt)
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
||||||
const res = await chain.run(input, [loggerHandler, handler])
|
const res = await chain.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.run(input, [loggerHandler])
|
const res = await chain.run(input, [loggerHandler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Inter
|
||||||
import { APIChain, createOpenAPIChain } from 'langchain/chains'
|
import { APIChain, createOpenAPIChain } from 'langchain/chains'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { getBaseClasses } from '../../../src/utils'
|
||||||
import { ChatOpenAI } from 'langchain/chat_models/openai'
|
import { ChatOpenAI } from 'langchain/chat_models/openai'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class OpenApiChain_Chains implements INode {
|
class OpenApiChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -61,13 +61,14 @@ class OpenApiChain_Chains implements INode {
|
||||||
async run(nodeData: INodeData, input: string, options: ICommonObject): Promise<string> {
|
async run(nodeData: INodeData, input: string, options: ICommonObject): Promise<string> {
|
||||||
const chain = await initChain(nodeData)
|
const chain = await initChain(nodeData)
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const res = await chain.run(input, [loggerHandler, handler])
|
const res = await chain.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.run(input, [loggerHandler])
|
const res = await chain.run(input, [loggerHandler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { getBaseClasses } from '../../../src/utils'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { PromptTemplate } from 'langchain/prompts'
|
import { PromptTemplate } from 'langchain/prompts'
|
||||||
import { API_RESPONSE_RAW_PROMPT_TEMPLATE, API_URL_RAW_PROMPT_TEMPLATE, APIChain } from './postCore'
|
import { API_RESPONSE_RAW_PROMPT_TEMPLATE, API_URL_RAW_PROMPT_TEMPLATE, APIChain } from './postCore'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class POSTApiChain_Chains implements INode {
|
class POSTApiChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -88,13 +88,14 @@ class POSTApiChain_Chains implements INode {
|
||||||
|
|
||||||
const chain = await getAPIChain(apiDocs, model, headers, urlPrompt, ansPrompt)
|
const chain = await getAPIChain(apiDocs, model, headers, urlPrompt, ansPrompt)
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
||||||
const res = await chain.run(input, [loggerHandler, handler])
|
const res = await chain.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.run(input, [loggerHandler])
|
const res = await chain.run(input, [loggerHandler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { getBaseClasses, mapChatHistory } from '../../../src/utils'
|
||||||
import { ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate } from 'langchain/prompts'
|
import { ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate } from 'langchain/prompts'
|
||||||
import { BufferMemory } from 'langchain/memory'
|
import { BufferMemory } from 'langchain/memory'
|
||||||
import { BaseChatModel } from 'langchain/chat_models/base'
|
import { BaseChatModel } from 'langchain/chat_models/base'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
import { flatten } from 'lodash'
|
import { flatten } from 'lodash'
|
||||||
import { Document } from 'langchain/document'
|
import { Document } from 'langchain/document'
|
||||||
|
|
||||||
|
|
@ -111,13 +111,14 @@ class ConversationChain_Chains implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const res = await chain.call({ input }, [loggerHandler, handler])
|
const res = await chain.call({ input }, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.response
|
return res?.response
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call({ input }, [loggerHandler])
|
const res = await chain.call({ input }, [loggerHandler, ...callbacks])
|
||||||
return res?.response
|
return res?.response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { ConversationalRetrievalQAChain, QAChainParams } from 'langchain/chains'
|
||||||
import { BaseRetriever } from 'langchain/schema/retriever'
|
import { BaseRetriever } from 'langchain/schema/retriever'
|
||||||
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
import { BufferMemory, BufferMemoryInput } from 'langchain/memory'
|
||||||
import { PromptTemplate } from 'langchain/prompts'
|
import { PromptTemplate } from 'langchain/prompts'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
import {
|
import {
|
||||||
default_map_reduce_template,
|
default_map_reduce_template,
|
||||||
default_qa_template,
|
default_qa_template,
|
||||||
|
|
@ -183,6 +183,7 @@ class ConversationalRetrievalQAChain_Chains implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(
|
const handler = new CustomChainHandler(
|
||||||
|
|
@ -191,7 +192,7 @@ class ConversationalRetrievalQAChain_Chains implements INode {
|
||||||
chainOption === 'refine' ? 4 : undefined,
|
chainOption === 'refine' ? 4 : undefined,
|
||||||
returnSourceDocuments
|
returnSourceDocuments
|
||||||
)
|
)
|
||||||
const res = await chain.call(obj, [loggerHandler, handler])
|
const res = await chain.call(obj, [loggerHandler, handler, ...callbacks])
|
||||||
if (chainOption === 'refine') {
|
if (chainOption === 'refine') {
|
||||||
if (res.output_text && res.sourceDocuments) {
|
if (res.output_text && res.sourceDocuments) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -204,7 +205,7 @@ class ConversationalRetrievalQAChain_Chains implements INode {
|
||||||
if (res.text && res.sourceDocuments) return res
|
if (res.text && res.sourceDocuments) return res
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(obj, [loggerHandler])
|
const res = await chain.call(obj, [loggerHandler, ...callbacks])
|
||||||
if (res.text && res.sourceDocuments) return res
|
if (res.text && res.sourceDocuments) return res
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { ICommonObject, INode, INodeData, INodeOutputsValue, INodeParams } from
|
||||||
import { getBaseClasses, handleEscapeCharacters } from '../../../src/utils'
|
import { getBaseClasses, handleEscapeCharacters } from '../../../src/utils'
|
||||||
import { LLMChain } from 'langchain/chains'
|
import { LLMChain } from 'langchain/chains'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class LLMChain_Chains implements INode {
|
class LLMChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -70,7 +70,7 @@ class LLMChain_Chains implements INode {
|
||||||
} else if (output === 'outputPrediction') {
|
} else if (output === 'outputPrediction') {
|
||||||
const chain = new LLMChain({ llm: model, prompt, verbose: process.env.DEBUG === 'true' ? true : false })
|
const chain = new LLMChain({ llm: model, prompt, verbose: process.env.DEBUG === 'true' ? true : false })
|
||||||
const inputVariables = chain.prompt.inputVariables as string[] // ["product"]
|
const inputVariables = chain.prompt.inputVariables as string[] // ["product"]
|
||||||
const res = await runPrediction(inputVariables, chain, input, promptValues, options)
|
const res = await runPrediction(inputVariables, chain, input, promptValues, options, nodeData)
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('\x1b[92m\x1b[1m\n*****OUTPUT PREDICTION*****\n\x1b[0m\x1b[0m')
|
console.log('\x1b[92m\x1b[1m\n*****OUTPUT PREDICTION*****\n\x1b[0m\x1b[0m')
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
@ -88,7 +88,7 @@ class LLMChain_Chains implements INode {
|
||||||
const inputVariables = nodeData.instance.prompt.inputVariables as string[] // ["product"]
|
const inputVariables = nodeData.instance.prompt.inputVariables as string[] // ["product"]
|
||||||
const chain = nodeData.instance as LLMChain
|
const chain = nodeData.instance as LLMChain
|
||||||
const promptValues = nodeData.inputs?.prompt.promptValues as ICommonObject
|
const promptValues = nodeData.inputs?.prompt.promptValues as ICommonObject
|
||||||
const res = await runPrediction(inputVariables, chain, input, promptValues, options)
|
const res = await runPrediction(inputVariables, chain, input, promptValues, options, nodeData)
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('\x1b[93m\x1b[1m\n*****FINAL RESULT*****\n\x1b[0m\x1b[0m')
|
console.log('\x1b[93m\x1b[1m\n*****FINAL RESULT*****\n\x1b[0m\x1b[0m')
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
@ -102,9 +102,12 @@ const runPrediction = async (
|
||||||
chain: LLMChain,
|
chain: LLMChain,
|
||||||
input: string,
|
input: string,
|
||||||
promptValuesRaw: ICommonObject,
|
promptValuesRaw: ICommonObject,
|
||||||
options: ICommonObject
|
options: ICommonObject,
|
||||||
|
nodeData: INodeData
|
||||||
) => {
|
) => {
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
const isStreaming = options.socketIO && options.socketIOClientId
|
const isStreaming = options.socketIO && options.socketIOClientId
|
||||||
const socketIO = isStreaming ? options.socketIO : undefined
|
const socketIO = isStreaming ? options.socketIO : undefined
|
||||||
const socketIOClientId = isStreaming ? options.socketIOClientId : ''
|
const socketIOClientId = isStreaming ? options.socketIOClientId : ''
|
||||||
|
|
@ -131,10 +134,10 @@ const runPrediction = async (
|
||||||
const options = { ...promptValues }
|
const options = { ...promptValues }
|
||||||
if (isStreaming) {
|
if (isStreaming) {
|
||||||
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
||||||
const res = await chain.call(options, [loggerHandler, handler])
|
const res = await chain.call(options, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(options, [loggerHandler])
|
const res = await chain.call(options, [loggerHandler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
} else if (seen.length === 1) {
|
} else if (seen.length === 1) {
|
||||||
|
|
@ -147,10 +150,10 @@ const runPrediction = async (
|
||||||
}
|
}
|
||||||
if (isStreaming) {
|
if (isStreaming) {
|
||||||
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
||||||
const res = await chain.call(options, [loggerHandler, handler])
|
const res = await chain.call(options, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(options, [loggerHandler])
|
const res = await chain.call(options, [loggerHandler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -159,10 +162,10 @@ const runPrediction = async (
|
||||||
} else {
|
} else {
|
||||||
if (isStreaming) {
|
if (isStreaming) {
|
||||||
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
const handler = new CustomChainHandler(socketIO, socketIOClientId)
|
||||||
const res = await chain.run(input, [loggerHandler, handler])
|
const res = await chain.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.run(input, [loggerHandler])
|
const res = await chain.run(input, [loggerHandler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ICommonObject, INode, INodeData, INodeParams, PromptRetriever } from '../../../src/Interface'
|
import { ICommonObject, INode, INodeData, INodeParams, PromptRetriever } from '../../../src/Interface'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { getBaseClasses } from '../../../src/utils'
|
||||||
import { MultiPromptChain } from 'langchain/chains'
|
import { MultiPromptChain } from 'langchain/chains'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class MultiPromptChain_Chains implements INode {
|
class MultiPromptChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -67,13 +67,14 @@ class MultiPromptChain_Chains implements INode {
|
||||||
const obj = { input }
|
const obj = { input }
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
||||||
const res = await chain.call(obj, [loggerHandler, handler])
|
const res = await chain.call(obj, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(obj, [loggerHandler])
|
const res = await chain.call(obj, [loggerHandler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ICommonObject, INode, INodeData, INodeParams, VectorStoreRetriever } from '../../../src/Interface'
|
import { ICommonObject, INode, INodeData, INodeParams, VectorStoreRetriever } from '../../../src/Interface'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { getBaseClasses } from '../../../src/utils'
|
||||||
import { MultiRetrievalQAChain } from 'langchain/chains'
|
import { MultiRetrievalQAChain } from 'langchain/chains'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class MultiRetrievalQAChain_Chains implements INode {
|
class MultiRetrievalQAChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -75,14 +75,15 @@ class MultiRetrievalQAChain_Chains implements INode {
|
||||||
|
|
||||||
const obj = { input }
|
const obj = { input }
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2, returnSourceDocuments)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2, returnSourceDocuments)
|
||||||
const res = await chain.call(obj, [loggerHandler, handler])
|
const res = await chain.call(obj, [loggerHandler, handler, ...callbacks])
|
||||||
if (res.text && res.sourceDocuments) return res
|
if (res.text && res.sourceDocuments) return res
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(obj, [loggerHandler])
|
const res = await chain.call(obj, [loggerHandler, ...callbacks])
|
||||||
if (res.text && res.sourceDocuments) return res
|
if (res.text && res.sourceDocuments) return res
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { RetrievalQAChain } from 'langchain/chains'
|
||||||
import { BaseRetriever } from 'langchain/schema/retriever'
|
import { BaseRetriever } from 'langchain/schema/retriever'
|
||||||
import { getBaseClasses } from '../../../src/utils'
|
import { getBaseClasses } from '../../../src/utils'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class RetrievalQAChain_Chains implements INode {
|
class RetrievalQAChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -53,13 +53,14 @@ class RetrievalQAChain_Chains implements INode {
|
||||||
query: input
|
query: input
|
||||||
}
|
}
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const res = await chain.call(obj, [loggerHandler, handler])
|
const res = await chain.call(obj, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(obj, [loggerHandler])
|
const res = await chain.call(obj, [loggerHandler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { DataSource } from 'typeorm'
|
||||||
import { SqlDatabase } from 'langchain/sql_db'
|
import { SqlDatabase } from 'langchain/sql_db'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { PromptTemplate, PromptTemplateInput } from 'langchain/prompts'
|
import { PromptTemplate, PromptTemplateInput } from 'langchain/prompts'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
import { DataSourceOptions } from 'typeorm/data-source'
|
import { DataSourceOptions } from 'typeorm/data-source'
|
||||||
|
|
||||||
type DatabaseType = 'sqlite' | 'postgres' | 'mssql' | 'mysql'
|
type DatabaseType = 'sqlite' | 'postgres' | 'mssql' | 'mysql'
|
||||||
|
|
@ -184,13 +184,14 @@ class SqlDatabaseChain_Chains implements INode {
|
||||||
customPrompt
|
customPrompt
|
||||||
)
|
)
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId, 2)
|
||||||
const res = await chain.run(input, [loggerHandler, handler])
|
const res = await chain.run(input, [loggerHandler, handler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.run(input, [loggerHandler])
|
const res = await chain.run(input, [loggerHandler, ...callbacks])
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { getBaseClasses } from '../../../src/utils'
|
||||||
import { VectorDBQAChain } from 'langchain/chains'
|
import { VectorDBQAChain } from 'langchain/chains'
|
||||||
import { BaseLanguageModel } from 'langchain/base_language'
|
import { BaseLanguageModel } from 'langchain/base_language'
|
||||||
import { VectorStore } from 'langchain/vectorstores'
|
import { VectorStore } from 'langchain/vectorstores'
|
||||||
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
|
import { ConsoleCallbackHandler, CustomChainHandler, additionalCallbacks } from '../../../src/handler'
|
||||||
|
|
||||||
class VectorDBQAChain_Chains implements INode {
|
class VectorDBQAChain_Chains implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -57,13 +57,14 @@ class VectorDBQAChain_Chains implements INode {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
const loggerHandler = new ConsoleCallbackHandler(options.logger)
|
||||||
|
const callbacks = await additionalCallbacks(nodeData, options)
|
||||||
|
|
||||||
if (options.socketIO && options.socketIOClientId) {
|
if (options.socketIO && options.socketIOClientId) {
|
||||||
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId)
|
||||||
const res = await chain.call(obj, [loggerHandler, handler])
|
const res = await chain.call(obj, [loggerHandler, handler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
} else {
|
} else {
|
||||||
const res = await chain.call(obj, [loggerHandler])
|
const res = await chain.call(obj, [loggerHandler, ...callbacks])
|
||||||
return res?.text
|
return res?.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,9 @@
|
||||||
"google-auth-library": "^9.0.0",
|
"google-auth-library": "^9.0.0",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"langchain": "^0.0.133",
|
"langchain": "^0.0.145",
|
||||||
|
"langfuse-langchain": "^1.0.14-alpha.0",
|
||||||
|
"langsmith": "^0.0.32",
|
||||||
"linkifyjs": "^4.1.1",
|
"linkifyjs": "^4.1.1",
|
||||||
"mammoth": "^1.5.1",
|
"mammoth": "^1.5.1",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@ import { BaseTracer, Run, BaseCallbackHandler } from 'langchain/callbacks'
|
||||||
import { AgentAction, ChainValues } from 'langchain/schema'
|
import { AgentAction, ChainValues } from 'langchain/schema'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { Server } from 'socket.io'
|
import { Server } from 'socket.io'
|
||||||
|
import { Client } from 'langsmith'
|
||||||
|
import { LangChainTracer } from 'langchain/callbacks'
|
||||||
|
import { getCredentialData, getCredentialParam } from './utils'
|
||||||
|
import { ICommonObject, INodeData } from './Interface'
|
||||||
|
import CallbackHandler from 'langfuse-langchain'
|
||||||
|
|
||||||
interface AgentRun extends Run {
|
interface AgentRun extends Run {
|
||||||
actions: AgentAction[]
|
actions: AgentAction[]
|
||||||
|
|
@ -178,3 +183,65 @@ export class CustomChainHandler extends BaseCallbackHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const additionalCallbacks = async (nodeData: INodeData, options: ICommonObject) => {
|
||||||
|
try {
|
||||||
|
if (!options.analytic) return []
|
||||||
|
|
||||||
|
const analytic = JSON.parse(options.analytic)
|
||||||
|
const callbacks: any = []
|
||||||
|
|
||||||
|
for (const provider in analytic) {
|
||||||
|
const providerStatus = analytic[provider].status as boolean
|
||||||
|
if (providerStatus) {
|
||||||
|
if (provider === 'langSmith') {
|
||||||
|
const credentialId = analytic[provider].credentialId as string
|
||||||
|
const langSmithProject = analytic[provider].projectName as string
|
||||||
|
|
||||||
|
const credentialData = await getCredentialData(credentialId ?? '', options)
|
||||||
|
const langSmithApiKey = getCredentialParam('langSmithApiKey', credentialData, nodeData)
|
||||||
|
const langSmithEndpoint = getCredentialParam('langSmithEndpoint', credentialData, nodeData)
|
||||||
|
|
||||||
|
const client = new Client({
|
||||||
|
apiUrl: langSmithEndpoint ?? 'https://api.smith.langchain.com',
|
||||||
|
apiKey: langSmithApiKey
|
||||||
|
})
|
||||||
|
|
||||||
|
const tracer = new LangChainTracer({
|
||||||
|
projectName: langSmithProject ?? 'default',
|
||||||
|
//@ts-ignore
|
||||||
|
client
|
||||||
|
})
|
||||||
|
callbacks.push(tracer)
|
||||||
|
} else if (provider === 'langFuse') {
|
||||||
|
const credentialId = analytic[provider].credentialId as string
|
||||||
|
const flushAt = analytic[provider].flushAt as string
|
||||||
|
const flushInterval = analytic[provider].flushInterval as string
|
||||||
|
const requestTimeout = analytic[provider].requestTimeout as string
|
||||||
|
const release = analytic[provider].release as string
|
||||||
|
|
||||||
|
const credentialData = await getCredentialData(credentialId ?? '', options)
|
||||||
|
const langFuseSecretKey = getCredentialParam('langFuseSecretKey', credentialData, nodeData)
|
||||||
|
const langFusePublicKey = getCredentialParam('langFusePublicKey', credentialData, nodeData)
|
||||||
|
const langFuseEndpoint = getCredentialParam('langFuseEndpoint', credentialData, nodeData)
|
||||||
|
|
||||||
|
const langFuseOptions: ICommonObject = {
|
||||||
|
secretKey: langFuseSecretKey,
|
||||||
|
publicKey: langFusePublicKey,
|
||||||
|
baseUrl: langFuseEndpoint ?? 'https://cloud.langfuse.com'
|
||||||
|
}
|
||||||
|
if (flushAt) langFuseOptions.flushAt = parseInt(flushAt, 10)
|
||||||
|
if (flushInterval) langFuseOptions.flushInterval = parseInt(flushInterval, 10)
|
||||||
|
if (requestTimeout) langFuseOptions.requestTimeout = parseInt(requestTimeout, 10)
|
||||||
|
if (release) langFuseOptions.release = release
|
||||||
|
|
||||||
|
const handler = new CallbackHandler(langFuseOptions)
|
||||||
|
callbacks.push(handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callbacks
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export interface IChatFlow {
|
||||||
deployed?: boolean
|
deployed?: boolean
|
||||||
isPublic?: boolean
|
isPublic?: boolean
|
||||||
apikeyid?: string
|
apikeyid?: string
|
||||||
|
analytic?: string
|
||||||
chatbotConfig?: string
|
chatbotConfig?: string
|
||||||
apiConfig?: any
|
apiConfig?: any
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export class NodesPool {
|
||||||
*/
|
*/
|
||||||
async initialize() {
|
async initialize() {
|
||||||
await this.initializeNodes()
|
await this.initializeNodes()
|
||||||
await this.initializeCrdentials()
|
await this.initializeCredentials()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,8 +34,6 @@ export class NodesPool {
|
||||||
const newNodeInstance = new nodeModule.nodeClass()
|
const newNodeInstance = new nodeModule.nodeClass()
|
||||||
newNodeInstance.filePath = file
|
newNodeInstance.filePath = file
|
||||||
|
|
||||||
this.componentNodes[newNodeInstance.name] = newNodeInstance
|
|
||||||
|
|
||||||
// Replace file icon with absolute path
|
// Replace file icon with absolute path
|
||||||
if (
|
if (
|
||||||
newNodeInstance.icon &&
|
newNodeInstance.icon &&
|
||||||
|
|
@ -46,7 +44,7 @@ export class NodesPool {
|
||||||
const filePath = file.replace(/\\/g, '/').split('/')
|
const filePath = file.replace(/\\/g, '/').split('/')
|
||||||
filePath.pop()
|
filePath.pop()
|
||||||
const nodeIconAbsolutePath = `${filePath.join('/')}/${newNodeInstance.icon}`
|
const nodeIconAbsolutePath = `${filePath.join('/')}/${newNodeInstance.icon}`
|
||||||
this.componentNodes[newNodeInstance.name].icon = nodeIconAbsolutePath
|
newNodeInstance.icon = nodeIconAbsolutePath
|
||||||
|
|
||||||
// Store icon path for componentCredentials
|
// Store icon path for componentCredentials
|
||||||
if (newNodeInstance.credential) {
|
if (newNodeInstance.credential) {
|
||||||
|
|
@ -55,6 +53,11 @@ export class NodesPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const skipCategories = ['Analytic']
|
||||||
|
if (!skipCategories.includes(newNodeInstance.category)) {
|
||||||
|
this.componentNodes[newNodeInstance.name] = newNodeInstance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -64,7 +67,7 @@ export class NodesPool {
|
||||||
/**
|
/**
|
||||||
* Initialize credentials
|
* Initialize credentials
|
||||||
*/
|
*/
|
||||||
private async initializeCrdentials() {
|
private async initializeCredentials() {
|
||||||
const packagePath = getNodeModulesPackagePath('flowise-components')
|
const packagePath = getNodeModulesPackagePath('flowise-components')
|
||||||
const nodesPath = path.join(packagePath, 'dist', 'credentials')
|
const nodesPath = path.join(packagePath, 'dist', 'credentials')
|
||||||
const nodeFiles = await this.getFiles(nodesPath)
|
const nodeFiles = await this.getFiles(nodesPath)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ export class ChatFlow implements IChatFlow {
|
||||||
@Column({ nullable: true, type: 'text' })
|
@Column({ nullable: true, type: 'text' })
|
||||||
apiConfig?: string
|
apiConfig?: string
|
||||||
|
|
||||||
|
@Column({ nullable: true, type: 'text' })
|
||||||
|
analytic?: string
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdDate: Date
|
createdDate: Date
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||||
|
|
||||||
|
export class AddAnalytic1694432361423 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`analytic\` TEXT;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`analytic\`;`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { ModifyChatMessage1693999022236 } from './1693999022236-ModifyChatMessag
|
||||||
import { ModifyCredential1693999261583 } from './1693999261583-ModifyCredential'
|
import { ModifyCredential1693999261583 } from './1693999261583-ModifyCredential'
|
||||||
import { ModifyTool1694001465232 } from './1694001465232-ModifyTool'
|
import { ModifyTool1694001465232 } from './1694001465232-ModifyTool'
|
||||||
import { AddApiConfig1694099200729 } from './1694099200729-AddApiConfig'
|
import { AddApiConfig1694099200729 } from './1694099200729-AddApiConfig'
|
||||||
|
import { AddAnalytic1694432361423 } from './1694432361423-AddAnalytic'
|
||||||
|
|
||||||
export const mysqlMigrations = [
|
export const mysqlMigrations = [
|
||||||
Init1693840429259,
|
Init1693840429259,
|
||||||
|
|
@ -11,5 +12,6 @@ export const mysqlMigrations = [
|
||||||
ModifyChatMessage1693999022236,
|
ModifyChatMessage1693999022236,
|
||||||
ModifyCredential1693999261583,
|
ModifyCredential1693999261583,
|
||||||
ModifyTool1694001465232,
|
ModifyTool1694001465232,
|
||||||
AddApiConfig1694099200729
|
AddApiConfig1694099200729,
|
||||||
|
AddAnalytic1694432361423
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||||
|
|
||||||
|
export class AddAnalytic1694432361423 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "chat_flow" ADD COLUMN "analytic" TEXT;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "chat_flow" DROP COLUMN "analytic";`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { ModifyChatMessage1693996694528 } from './1693996694528-ModifyChatMessag
|
||||||
import { ModifyCredential1693997070000 } from './1693997070000-ModifyCredential'
|
import { ModifyCredential1693997070000 } from './1693997070000-ModifyCredential'
|
||||||
import { ModifyTool1693997339912 } from './1693997339912-ModifyTool'
|
import { ModifyTool1693997339912 } from './1693997339912-ModifyTool'
|
||||||
import { AddApiConfig1694099183389 } from './1694099183389-AddApiConfig'
|
import { AddApiConfig1694099183389 } from './1694099183389-AddApiConfig'
|
||||||
|
import { AddAnalytic1694432361423 } from './1694432361423-AddAnalytic'
|
||||||
|
|
||||||
export const postgresMigrations = [
|
export const postgresMigrations = [
|
||||||
Init1693891895163,
|
Init1693891895163,
|
||||||
|
|
@ -11,5 +12,6 @@ export const postgresMigrations = [
|
||||||
ModifyChatMessage1693996694528,
|
ModifyChatMessage1693996694528,
|
||||||
ModifyCredential1693997070000,
|
ModifyCredential1693997070000,
|
||||||
ModifyTool1693997339912,
|
ModifyTool1693997339912,
|
||||||
AddApiConfig1694099183389
|
AddApiConfig1694099183389,
|
||||||
|
AddAnalytic1694432361423
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||||
|
|
||||||
|
export class AddAnalytic1694432361423 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "chat_flow" ADD COLUMN "analytic" TEXT;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "chat_flow" DROP COLUMN "analytic";`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { ModifyChatMessage1693921865247 } from './1693921865247-ModifyChatMessag
|
||||||
import { ModifyCredential1693923551694 } from './1693923551694-ModifyCredential'
|
import { ModifyCredential1693923551694 } from './1693923551694-ModifyCredential'
|
||||||
import { ModifyTool1693924207475 } from './1693924207475-ModifyTool'
|
import { ModifyTool1693924207475 } from './1693924207475-ModifyTool'
|
||||||
import { AddApiConfig1694090982460 } from './1694090982460-AddApiConfig'
|
import { AddApiConfig1694090982460 } from './1694090982460-AddApiConfig'
|
||||||
|
import { AddAnalytic1694432361423 } from './1694432361423-AddAnalytic'
|
||||||
|
|
||||||
export const sqliteMigrations = [
|
export const sqliteMigrations = [
|
||||||
Init1693835579790,
|
Init1693835579790,
|
||||||
|
|
@ -11,5 +12,6 @@ export const sqliteMigrations = [
|
||||||
ModifyChatMessage1693921865247,
|
ModifyChatMessage1693921865247,
|
||||||
ModifyCredential1693923551694,
|
ModifyCredential1693923551694,
|
||||||
ModifyTool1693924207475,
|
ModifyTool1693924207475,
|
||||||
AddApiConfig1694090982460
|
AddApiConfig1694090982460,
|
||||||
|
AddAnalytic1694432361423
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -980,13 +980,15 @@ export class App {
|
||||||
socketIOClientId: incomingInput.socketIOClientId,
|
socketIOClientId: incomingInput.socketIOClientId,
|
||||||
logger,
|
logger,
|
||||||
appDataSource: this.AppDataSource,
|
appDataSource: this.AppDataSource,
|
||||||
databaseEntities
|
databaseEntities,
|
||||||
|
analytic: chatflow.analytic
|
||||||
})
|
})
|
||||||
: await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
: await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
|
||||||
chatHistory: incomingInput.history,
|
chatHistory: incomingInput.history,
|
||||||
logger,
|
logger,
|
||||||
appDataSource: this.AppDataSource,
|
appDataSource: this.AppDataSource,
|
||||||
databaseEntities
|
databaseEntities,
|
||||||
|
analytic: chatflow.analytic
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.debug(`[server]: Finished running ${nodeToExecuteData.label} (${nodeToExecuteData.id})`)
|
logger.debug(`[server]: Finished running ${nodeToExecuteData.label} (${nodeToExecuteData.id})`)
|
||||||
|
|
|
||||||
|
|
@ -448,10 +448,11 @@ export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig:
|
||||||
// If overrideConfig[key] is object
|
// If overrideConfig[key] is object
|
||||||
if (overrideConfig[config] && typeof overrideConfig[config] === 'object') {
|
if (overrideConfig[config] && typeof overrideConfig[config] === 'object') {
|
||||||
const nodeIds = Object.keys(overrideConfig[config])
|
const nodeIds = Object.keys(overrideConfig[config])
|
||||||
if (!nodeIds.includes(flowNodeData.id)) continue
|
if (nodeIds.includes(flowNodeData.id)) {
|
||||||
else paramsObj[config] = overrideConfig[config][flowNodeData.id]
|
paramsObj[config] = overrideConfig[config][flowNodeData.id]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let paramValue = overrideConfig[config] ?? paramsObj[config]
|
let paramValue = overrideConfig[config] ?? paramsObj[config]
|
||||||
// Check if boolean
|
// Check if boolean
|
||||||
|
|
@ -877,12 +878,14 @@ export const decryptCredentialData = async (
|
||||||
* @returns {Credential}
|
* @returns {Credential}
|
||||||
*/
|
*/
|
||||||
export const transformToCredentialEntity = async (body: ICredentialReqBody): Promise<Credential> => {
|
export const transformToCredentialEntity = async (body: ICredentialReqBody): Promise<Credential> => {
|
||||||
const encryptedData = await encryptCredentialData(body.plainDataObj)
|
const credentialBody: ICommonObject = {
|
||||||
|
|
||||||
const credentialBody = {
|
|
||||||
name: body.name,
|
name: body.name,
|
||||||
credentialName: body.credentialName,
|
credentialName: body.credentialName
|
||||||
encryptedData
|
}
|
||||||
|
|
||||||
|
if (body.plainDataObj) {
|
||||||
|
const encryptedData = await encryptCredentialData(body.plainDataObj)
|
||||||
|
credentialBody.encryptedData = encryptedData
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCredential = new Credential()
|
const newCredential = new Credential()
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -1,8 +1,8 @@
|
||||||
// assets
|
// assets
|
||||||
import { IconTrash, IconFileUpload, IconFileExport, IconCopy } from '@tabler/icons'
|
import { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch } from '@tabler/icons'
|
||||||
|
|
||||||
// constant
|
// constant
|
||||||
const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy }
|
const icons = { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconSearch }
|
||||||
|
|
||||||
// ==============================|| SETTINGS MENU ITEMS ||============================== //
|
// ==============================|| SETTINGS MENU ITEMS ||============================== //
|
||||||
|
|
||||||
|
|
@ -32,6 +32,13 @@ const settings = {
|
||||||
url: '',
|
url: '',
|
||||||
icon: icons.IconFileExport
|
icon: icons.IconFileExport
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'analyseChatflow',
|
||||||
|
title: 'Analyse Chatflow',
|
||||||
|
type: 'item',
|
||||||
|
url: '',
|
||||||
|
icon: icons.IconSearch
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'deleteChatflow',
|
id: 'deleteChatflow',
|
||||||
title: 'Delete Chatflow',
|
title: 'Delete Chatflow',
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,4 @@ export const maxScroll = 100000
|
||||||
export const baseURL = process.env.NODE_ENV === 'production' ? window.location.origin : window.location.origin.replace(':8080', ':3000')
|
export const baseURL = process.env.NODE_ENV === 'production' ? window.location.origin : window.location.origin.replace(':8080', ':3000')
|
||||||
export const uiBaseURL = window.location.origin
|
export const uiBaseURL = window.location.origin
|
||||||
export const FLOWISE_CREDENTIAL_ID = 'FLOWISE_CREDENTIAL_ID'
|
export const FLOWISE_CREDENTIAL_ID = 'FLOWISE_CREDENTIAL_ID'
|
||||||
|
export const REDACTED_CREDENTIAL_VALUE = '_FLOWISE_BLANK_07167752-1a71-43b1-bf8f-4f32252165db'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,358 @@
|
||||||
|
import { createPortal } from 'react-dom'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction, SET_CHATFLOW } from 'store/actions'
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import {
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
DialogActions,
|
||||||
|
Accordion,
|
||||||
|
AccordionSummary,
|
||||||
|
AccordionDetails,
|
||||||
|
ListItem,
|
||||||
|
ListItemAvatar,
|
||||||
|
ListItemText
|
||||||
|
} from '@mui/material'
|
||||||
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
|
||||||
|
import { IconX } from '@tabler/icons'
|
||||||
|
|
||||||
|
// Project import
|
||||||
|
import CredentialInputHandler from 'views/canvas/CredentialInputHandler'
|
||||||
|
import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser'
|
||||||
|
import { SwitchInput } from 'ui-component/switch/Switch'
|
||||||
|
import { Input } from 'ui-component/input/Input'
|
||||||
|
import { StyledButton } from 'ui-component/button/StyledButton'
|
||||||
|
import langsmithPNG from 'assets/images/langchain.png'
|
||||||
|
import langfusePNG from 'assets/images/langfuse.png'
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
|
||||||
|
import useNotifier from 'utils/useNotifier'
|
||||||
|
|
||||||
|
// API
|
||||||
|
import chatflowsApi from 'api/chatflows'
|
||||||
|
|
||||||
|
const analyticProviders = [
|
||||||
|
{
|
||||||
|
label: 'LangSmith',
|
||||||
|
name: 'langSmith',
|
||||||
|
icon: langsmithPNG,
|
||||||
|
url: 'https://smith.langchain.com',
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
label: 'Connect Credential',
|
||||||
|
name: 'credential',
|
||||||
|
type: 'credential',
|
||||||
|
credentialNames: ['langsmithApi']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Project Name',
|
||||||
|
name: 'projectName',
|
||||||
|
type: 'string',
|
||||||
|
optional: true,
|
||||||
|
description: 'If not provided, default will be used',
|
||||||
|
placeholder: 'default'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'On/Off',
|
||||||
|
name: 'status',
|
||||||
|
type: 'boolean',
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'LangFuse',
|
||||||
|
name: 'langFuse',
|
||||||
|
icon: langfusePNG,
|
||||||
|
url: 'https://langfuse.com',
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
label: 'Connect Credential',
|
||||||
|
name: 'credential',
|
||||||
|
type: 'credential',
|
||||||
|
credentialNames: ['langfuseApi']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Flush At',
|
||||||
|
name: 'flushAt',
|
||||||
|
type: 'number',
|
||||||
|
optional: true,
|
||||||
|
description: 'Number of queued requests'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Flush Interval',
|
||||||
|
name: 'flushInterval',
|
||||||
|
type: 'number',
|
||||||
|
optional: true,
|
||||||
|
description: 'Interval in ms to flush requests'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Request Timeout',
|
||||||
|
name: 'requestTimeout',
|
||||||
|
type: 'number',
|
||||||
|
optional: true,
|
||||||
|
description: 'Timeout in ms for requests'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Release',
|
||||||
|
name: 'release',
|
||||||
|
type: 'string',
|
||||||
|
optional: true,
|
||||||
|
description: 'The release number/hash of the application to provide analytics grouped by release'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'On/Off',
|
||||||
|
name: 'status',
|
||||||
|
type: 'boolean',
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const AnalyseFlowDialog = ({ show, dialogProps, onCancel }) => {
|
||||||
|
const portalElement = document.getElementById('portal')
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
useNotifier()
|
||||||
|
|
||||||
|
const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args))
|
||||||
|
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
|
||||||
|
|
||||||
|
const [analytic, setAnalytic] = useState({})
|
||||||
|
const [providerExpanded, setProviderExpanded] = useState({})
|
||||||
|
|
||||||
|
const onSave = async () => {
|
||||||
|
try {
|
||||||
|
const saveResp = await chatflowsApi.updateChatflow(dialogProps.chatflow.id, {
|
||||||
|
analytic: JSON.stringify(analytic)
|
||||||
|
})
|
||||||
|
if (saveResp.data) {
|
||||||
|
enqueueSnackbar({
|
||||||
|
message: 'Analytic Configuration Saved',
|
||||||
|
options: {
|
||||||
|
key: new Date().getTime() + Math.random(),
|
||||||
|
variant: 'success',
|
||||||
|
action: (key) => (
|
||||||
|
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
|
||||||
|
<IconX />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dispatch({ type: SET_CHATFLOW, chatflow: saveResp.data })
|
||||||
|
}
|
||||||
|
onCancel()
|
||||||
|
} catch (error) {
|
||||||
|
const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}`
|
||||||
|
enqueueSnackbar({
|
||||||
|
message: `Failed to save Analytic Configuration: ${errorData}`,
|
||||||
|
options: {
|
||||||
|
key: new Date().getTime() + Math.random(),
|
||||||
|
variant: 'error',
|
||||||
|
persist: true,
|
||||||
|
action: (key) => (
|
||||||
|
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
|
||||||
|
<IconX />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setValue = (value, providerName, inputParamName) => {
|
||||||
|
let newVal = {}
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(analytic, providerName)) {
|
||||||
|
newVal = { ...analytic, [providerName]: {} }
|
||||||
|
} else {
|
||||||
|
newVal = { ...analytic }
|
||||||
|
}
|
||||||
|
|
||||||
|
newVal[providerName][inputParamName] = value
|
||||||
|
setAnalytic(newVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAccordionChange = (providerName) => (event, isExpanded) => {
|
||||||
|
const accordianProviders = { ...providerExpanded }
|
||||||
|
accordianProviders[providerName] = isExpanded
|
||||||
|
setProviderExpanded(accordianProviders)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dialogProps.chatflow && dialogProps.chatflow.analytic) {
|
||||||
|
try {
|
||||||
|
setAnalytic(JSON.parse(dialogProps.chatflow.analytic))
|
||||||
|
} catch (e) {
|
||||||
|
setAnalytic({})
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
setAnalytic({})
|
||||||
|
setProviderExpanded({})
|
||||||
|
}
|
||||||
|
}, [dialogProps])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (show) dispatch({ type: SHOW_CANVAS_DIALOG })
|
||||||
|
else dispatch({ type: HIDE_CANVAS_DIALOG })
|
||||||
|
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
|
||||||
|
}, [show, dispatch])
|
||||||
|
|
||||||
|
const component = show ? (
|
||||||
|
<Dialog
|
||||||
|
onClose={onCancel}
|
||||||
|
open={show}
|
||||||
|
fullWidth
|
||||||
|
maxWidth='sm'
|
||||||
|
aria-labelledby='alert-dialog-title'
|
||||||
|
aria-describedby='alert-dialog-description'
|
||||||
|
>
|
||||||
|
<DialogTitle sx={{ fontSize: '1rem' }} id='alert-dialog-title'>
|
||||||
|
Analyse Chatflow
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
{analyticProviders.map((provider, index) => (
|
||||||
|
<Accordion
|
||||||
|
expanded={providerExpanded[provider.name] || false}
|
||||||
|
onChange={handleAccordionChange(provider.name)}
|
||||||
|
disableGutters
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls={provider.name} id={provider.name}>
|
||||||
|
<ListItem style={{ padding: 0, margin: 0 }} alignItems='center'>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundColor: 'white'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
padding: 10,
|
||||||
|
objectFit: 'contain'
|
||||||
|
}}
|
||||||
|
alt='AI'
|
||||||
|
src={provider.icon}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
sx={{ ml: 1 }}
|
||||||
|
primary={provider.label}
|
||||||
|
secondary={
|
||||||
|
<a target='_blank' rel='noreferrer' href={provider.url}>
|
||||||
|
{provider.url}
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{analytic[provider.name] && analytic[provider.name].status && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
background: '#d8f3dc',
|
||||||
|
borderRadius: 15,
|
||||||
|
padding: 5,
|
||||||
|
paddingLeft: 7,
|
||||||
|
paddingRight: 7,
|
||||||
|
marginRight: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 15,
|
||||||
|
height: 15,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundColor: '#70e000'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ color: '#006400', marginLeft: 10 }}>ON</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ListItem>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
{provider.inputs.map((inputParam, index) => (
|
||||||
|
<Box key={index} sx={{ p: 2 }}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Typography>
|
||||||
|
{inputParam.label}
|
||||||
|
{!inputParam.optional && <span style={{ color: 'red' }}> *</span>}
|
||||||
|
{inputParam.description && (
|
||||||
|
<TooltipWithParser style={{ marginLeft: 10 }} title={inputParam.description} />
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
{providerExpanded[provider.name] && inputParam.type === 'credential' && (
|
||||||
|
<CredentialInputHandler
|
||||||
|
data={analytic[provider.name] ? { credential: analytic[provider.name].credentialId } : {}}
|
||||||
|
inputParam={inputParam}
|
||||||
|
onSelect={(newValue) => setValue(newValue, provider.name, 'credentialId')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{providerExpanded[provider.name] && inputParam.type === 'boolean' && (
|
||||||
|
<SwitchInput
|
||||||
|
onChange={(newValue) => setValue(newValue, provider.name, inputParam.name)}
|
||||||
|
value={
|
||||||
|
analytic[provider.name]
|
||||||
|
? analytic[provider.name][inputParam.name]
|
||||||
|
: inputParam.default ?? false
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{providerExpanded[provider.name] &&
|
||||||
|
(inputParam.type === 'string' ||
|
||||||
|
inputParam.type === 'password' ||
|
||||||
|
inputParam.type === 'number') && (
|
||||||
|
<Input
|
||||||
|
inputParam={inputParam}
|
||||||
|
onChange={(newValue) => setValue(newValue, provider.name, inputParam.name)}
|
||||||
|
value={
|
||||||
|
analytic[provider.name]
|
||||||
|
? analytic[provider.name][inputParam.name]
|
||||||
|
: inputParam.default ?? ''
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
))}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<StyledButton variant='contained' onClick={onSave}>
|
||||||
|
Save
|
||||||
|
</StyledButton>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
) : null
|
||||||
|
|
||||||
|
return createPortal(component, portalElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyseFlowDialog.propTypes = {
|
||||||
|
show: PropTypes.bool,
|
||||||
|
dialogProps: PropTypes.object,
|
||||||
|
onCancel: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnalyseFlowDialog
|
||||||
|
|
@ -22,7 +22,7 @@ export const SwitchInput = ({ value, onChange, disabled = false }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchInput.propTypes = {
|
SwitchInput.propTypes = {
|
||||||
value: PropTypes.string,
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
disabled: PropTypes.bool
|
disabled: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { IconSettings, IconChevronLeft, IconDeviceFloppy, IconPencil, IconCheck,
|
||||||
import Settings from 'views/settings'
|
import Settings from 'views/settings'
|
||||||
import SaveChatflowDialog from 'ui-component/dialog/SaveChatflowDialog'
|
import SaveChatflowDialog from 'ui-component/dialog/SaveChatflowDialog'
|
||||||
import APICodeDialog from 'views/chatflows/APICodeDialog'
|
import APICodeDialog from 'views/chatflows/APICodeDialog'
|
||||||
|
import AnalyseFlowDialog from 'ui-component/dialog/AnalyseFlowDialog'
|
||||||
|
|
||||||
// API
|
// API
|
||||||
import chatflowsApi from 'api/chatflows'
|
import chatflowsApi from 'api/chatflows'
|
||||||
|
|
@ -41,6 +42,8 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||||
const [flowDialogOpen, setFlowDialogOpen] = useState(false)
|
const [flowDialogOpen, setFlowDialogOpen] = useState(false)
|
||||||
const [apiDialogOpen, setAPIDialogOpen] = useState(false)
|
const [apiDialogOpen, setAPIDialogOpen] = useState(false)
|
||||||
const [apiDialogProps, setAPIDialogProps] = useState({})
|
const [apiDialogProps, setAPIDialogProps] = useState({})
|
||||||
|
const [analyseDialogOpen, setAnalyseDialogOpen] = useState(false)
|
||||||
|
const [analyseDialogProps, setAnalyseDialogProps] = useState({})
|
||||||
|
|
||||||
const updateChatflowApi = useApi(chatflowsApi.updateChatflow)
|
const updateChatflowApi = useApi(chatflowsApi.updateChatflow)
|
||||||
const canvas = useSelector((state) => state.canvas)
|
const canvas = useSelector((state) => state.canvas)
|
||||||
|
|
@ -50,6 +53,12 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||||
|
|
||||||
if (setting === 'deleteChatflow') {
|
if (setting === 'deleteChatflow') {
|
||||||
handleDeleteFlow()
|
handleDeleteFlow()
|
||||||
|
} else if (setting === 'analyseChatflow') {
|
||||||
|
setAnalyseDialogProps({
|
||||||
|
title: 'Analyse Chatflow',
|
||||||
|
chatflow: chatflow
|
||||||
|
})
|
||||||
|
setAnalyseDialogOpen(true)
|
||||||
} else if (setting === 'duplicateChatflow') {
|
} else if (setting === 'duplicateChatflow') {
|
||||||
try {
|
try {
|
||||||
localStorage.setItem('duplicatedFlowData', chatflow.flowData)
|
localStorage.setItem('duplicatedFlowData', chatflow.flowData)
|
||||||
|
|
@ -357,6 +366,7 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
|
||||||
onConfirm={onConfirmSaveName}
|
onConfirm={onConfirmSaveName}
|
||||||
/>
|
/>
|
||||||
<APICodeDialog show={apiDialogOpen} dialogProps={apiDialogProps} onCancel={() => setAPIDialogOpen(false)} />
|
<APICodeDialog show={apiDialogOpen} dialogProps={apiDialogProps} onCancel={() => setAPIDialogOpen(false)} />
|
||||||
|
<AnalyseFlowDialog show={analyseDialogOpen} dialogProps={analyseDialogProps} onCancel={() => setAnalyseDialogOpen(false)} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import useApi from 'hooks/useApi'
|
||||||
import useNotifier from 'utils/useNotifier'
|
import useNotifier from 'utils/useNotifier'
|
||||||
|
|
||||||
// const
|
// const
|
||||||
import { baseURL } from 'store/constant'
|
import { baseURL, REDACTED_CREDENTIAL_VALUE } from 'store/constant'
|
||||||
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
|
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
|
||||||
|
|
||||||
const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
|
const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
|
||||||
|
|
@ -118,7 +118,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
|
||||||
onConfirm(createResp.data.id)
|
onConfirm(createResp.data.id)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}`
|
const errorData = typeof err === 'string' ? err : err.response.data || `${err.response.status}: ${err.response.statusText}`
|
||||||
enqueueSnackbar({
|
enqueueSnackbar({
|
||||||
message: `Failed to add new Credential: ${errorData}`,
|
message: `Failed to add new Credential: ${errorData}`,
|
||||||
options: {
|
options: {
|
||||||
|
|
@ -138,11 +138,20 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
|
||||||
|
|
||||||
const saveCredential = async () => {
|
const saveCredential = async () => {
|
||||||
try {
|
try {
|
||||||
const saveResp = await credentialsApi.updateCredential(credential.id, {
|
const saveObj = {
|
||||||
name,
|
name,
|
||||||
credentialName: componentCredential.name,
|
credentialName: componentCredential.name
|
||||||
plainDataObj: credentialData
|
}
|
||||||
})
|
|
||||||
|
let plainDataObj = {}
|
||||||
|
for (const key in credentialData) {
|
||||||
|
if (credentialData[key] !== REDACTED_CREDENTIAL_VALUE) {
|
||||||
|
plainDataObj[key] = credentialData[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(plainDataObj).length) saveObj.plainDataObj = plainDataObj
|
||||||
|
|
||||||
|
const saveResp = await credentialsApi.updateCredential(credential.id, saveObj)
|
||||||
if (saveResp.data) {
|
if (saveResp.data) {
|
||||||
enqueueSnackbar({
|
enqueueSnackbar({
|
||||||
message: 'Credential saved',
|
message: 'Credential saved',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue