diff --git a/packages/components/credentials/LLMonitorApi.credential.ts b/packages/components/credentials/LLMonitorApi.credential.ts new file mode 100644 index 00000000..97b195ec --- /dev/null +++ b/packages/components/credentials/LLMonitorApi.credential.ts @@ -0,0 +1,33 @@ +import { INodeParams, INodeCredential } from '../src/Interface' + +class LLMonitorApi implements INodeCredential { + label: string + name: string + version: number + description: string + inputs: INodeParams[] + + constructor() { + this.label = 'LLMonitor API' + this.name = 'llmonitorApi' + this.version = 1.0 + this.description = + 'Refer to official guide on how to get API key on Langsmith' + this.inputs = [ + { + label: 'APP ID', + name: 'llmonitorAppId', + type: 'password', + placeholder: '' + }, + { + label: 'Endpoint', + name: 'llmonitorEndpoint', + type: 'string', + default: 'https://app.llmonitor.com' + } + ] + } +} + +module.exports = { credClass: LLMonitorApi } diff --git a/packages/components/nodes/analytic/LLMonitor/LLMonitor.ts b/packages/components/nodes/analytic/LLMonitor/LLMonitor.ts new file mode 100644 index 00000000..a1ae317c --- /dev/null +++ b/packages/components/nodes/analytic/LLMonitor/LLMonitor.ts @@ -0,0 +1,33 @@ +import { INode, INodeParams } from '../../../src/Interface' + +class LLMonitor_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 = 'LLMonitor' + this.name = 'llmonitor' + this.version = 1.0 + this.type = 'LLMonitor' + this.icon = 'llmonitor.png' + this.category = 'Analytic' + this.baseClasses = [this.type] + this.inputs = [] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['llmonitorApi'] + } + } +} + +module.exports = { nodeClass: LLMonitor_Analytic } diff --git a/packages/components/nodes/analytic/LLMonitor/llmonitor.png b/packages/components/nodes/analytic/LLMonitor/llmonitor.png new file mode 100644 index 00000000..d50a7044 Binary files /dev/null and b/packages/components/nodes/analytic/LLMonitor/llmonitor.png differ diff --git a/packages/components/package.json b/packages/components/package.json index a69b8f26..2512104e 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -46,6 +46,7 @@ "langfuse-langchain": "^1.0.14-alpha.0", "langsmith": "^0.0.32", "linkifyjs": "^4.1.1", + "llmonitor": "^0.5.5", "mammoth": "^1.5.1", "moment": "^2.29.3", "mysql2": "^3.5.1", diff --git a/packages/components/src/handler.ts b/packages/components/src/handler.ts index f13719ce..10f9a214 100644 --- a/packages/components/src/handler.ts +++ b/packages/components/src/handler.ts @@ -4,6 +4,7 @@ import { Logger } from 'winston' import { Server } from 'socket.io' import { Client } from 'langsmith' import { LangChainTracer } from 'langchain/callbacks' +import { LLMonitorHandler } from 'langchain/callbacks/handlers/llmonitor' import { getCredentialData, getCredentialParam } from './utils' import { ICommonObject, INodeData } from './Interface' import CallbackHandler from 'langfuse-langchain' @@ -194,11 +195,11 @@ export const additionalCallbacks = async (nodeData: INodeData, options: ICommonO for (const provider in analytic) { const providerStatus = analytic[provider].status as boolean if (providerStatus) { + const credentialId = analytic[provider].credentialId as string + const credentialData = await getCredentialData(credentialId ?? '', options) 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) @@ -214,13 +215,11 @@ export const additionalCallbacks = async (nodeData: INodeData, options: ICommonO }) 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) @@ -237,6 +236,17 @@ export const additionalCallbacks = async (nodeData: INodeData, options: ICommonO const handler = new CallbackHandler(langFuseOptions) callbacks.push(handler) + } else if (provider === 'llmonitor') { + const llmonitorAppId = getCredentialParam('llmonitorAppId', credentialData, nodeData) + const llmonitorEndpoint = getCredentialParam('llmonitorEndpoint', credentialData, nodeData) + + const llmonitorFields: ICommonObject = { + appId: llmonitorAppId, + apiUrl: llmonitorEndpoint ?? 'https://app.llmonitor.com' + } + + const handler = new LLMonitorHandler(llmonitorFields) + callbacks.push(handler) } } } diff --git a/packages/ui/src/assets/images/llmonitor.png b/packages/ui/src/assets/images/llmonitor.png new file mode 100644 index 00000000..d50a7044 Binary files /dev/null and b/packages/ui/src/assets/images/llmonitor.png differ diff --git a/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js b/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js index 1ed68fb5..2d9a7d91 100644 --- a/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js +++ b/packages/ui/src/ui-component/dialog/AnalyseFlowDialog.js @@ -31,6 +31,7 @@ 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' +import llmonitorPNG from 'assets/images/llmonitor.png' // store import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions' @@ -115,6 +116,26 @@ const analyticProviders = [ optional: true } ] + }, + { + label: 'LLMonitor', + name: 'llmonitor', + icon: llmonitorPNG, + url: 'https://llmonitor.com', + inputs: [ + { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['llmonitorApi'] + }, + { + label: 'On/Off', + name: 'status', + type: 'boolean', + optional: true + } + ] } ]