diff --git a/packages/components/credentials/GigaChat.credential.ts b/packages/components/credentials/GigaChat.credential.ts new file mode 100644 index 00000000000..745a6343e72 --- /dev/null +++ b/packages/components/credentials/GigaChat.credential.ts @@ -0,0 +1,26 @@ +import { INodeCredential, INodeParams } from "../src/Interface" + +class GigaChatApi implements INodeCredential { + label: string + name: string + version: number + description: string + inputs: INodeParams[] + + constructor() { + this.label = 'GigaChat API' + this.name = 'gigaChatApi' + this.version = 1.0 + this.description = 'You can get the Credentials token from GigaChat API in Developer Console' + this.inputs = [ + { + label: 'Access Token', + name: 'accessToken', + type: 'password', + placeholder: '' + } + ] + } +} + +module.exports = { credClass: GigaChatApi } \ No newline at end of file diff --git a/packages/components/nodes/chatmodels/ChatGigaChat/ChatGigaChat.ts b/packages/components/nodes/chatmodels/ChatGigaChat/ChatGigaChat.ts new file mode 100644 index 00000000000..2a3e0584be8 --- /dev/null +++ b/packages/components/nodes/chatmodels/ChatGigaChat/ChatGigaChat.ts @@ -0,0 +1,162 @@ +import { GigaChat as GigaChatLangchain } from 'langchain-gigachat' +import { FlowiseGigaChat } from './FlowiseChatGigaChat' + +import { getBaseClasses, getCredentialData } from '../../../src/utils' +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' + +const defaultBaseUrl = 'https://gigachat.devices.sberbank.ru/api/v1/' + +class ChatGigaChat implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + credential: INodeParams + inputs: INodeParams[] + + constructor() { + this.label = 'ChatGigaChat' + this.name = 'chatgigachat' + this.version = 2.0 + this.type = 'ChatGigaChat' + this.icon = 'GigaChat.svg' + this.category = 'Chat Models' + this.description = 'Wrapper around GigaChat large language models that use the Chat endpoint' + this.baseClasses = [this.type, ...getBaseClasses(GigaChatLangchain)] + this.credential = { + label: 'Credential', + name: 'credential', + type: 'credential', + credentialNames: ['gigaChatApi'] + } + this.inputs = [ + { + label: 'Model Name', + name: 'modelName', + type: 'options', + options: [ + { + label: 'GigaChat v2', + name: 'GigaChat-2', + description: 'The most advanced model' + }, + { + label: 'GigaChat Pro v2', + name: 'GigaChat-2-Pro', + description: 'The most advanced model Pro' + }, + { + label: 'GigaChat Max v2', + name: 'GigaChat-2-Max', + description: 'The most advanced model Max' + }, + { + label: 'GigaChat Max', + name: 'GigaChat-Max', + description: 'An advanced model for complex tasks that require a high level of creativity and quality of work' + }, + { + label: 'GigaChat Pro', + name: 'GigaChat-Pro', + description: + 'the model follows complex instructions more effectively and can handle more sophisticated tasks: the quality of summarization, rewriting and editing texts, and answering various questions has improved significantly' + }, + { + label: 'GigaChat Plus', + name: 'GigaChat-Plus', + description: + 'Ideally suited for tasks that require sending a large amount of information in a single request.' + }, + { + label: 'GigaChat', + name: 'GigaChat', + description: + 'Suitable for solving simpler tasks that require maximum processing speed. At the same time, the cost of using the model is lower because it requires fewer computational resources.' + } + ], + default: 'GigaChat-2-Pro' + }, + { + label: 'Scope', + name: 'scope', + type: 'options', + description: 'a required field in the request body that specifies which API version the request is being made to', + options: [ + { + label: 'GIGACHAT_API_PERS', + name: 'GIGACHAT_API_PERS', + description: 'access for individuals' + }, + { + label: 'GIGACHAT_API_B2B', + name: 'GIGACHAT_API_B2B', + description: 'access for sole proprietors and legal entities through paid packages' + }, + { + label: 'GIGACHAT_API_CORP', + name: 'GIGACHAT_API_CORP', + description: 'access for sole proprietors and legal entities on a pay-as-you-go basis' + } + ], + default: 'GIGACHAT_API_PERS' + }, + { + label: 'Base URL', + name: 'baseUrl', + type: 'string', + default: defaultBaseUrl, + description: 'API URL', + optional: false + }, + { + label: 'Temperature', + name: 'temperature', + type: 'number', + step: 0.1, + default: 1, + optional: true + }, + { + label: 'Timeout', + name: 'timeout', + type: 'number', + step: 1, + default: 60000, + optional: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const temperature = Number(nodeData.inputs?.temperature || 1) + const scope = String(nodeData.inputs?.scope || 'GIGACHAT_API_PERS') + const modelName = nodeData.inputs?.modelName as string + const timeout = Number(nodeData.inputs?.timeout || 60000) + const baseUrl = String(nodeData.inputs?.baseUrl || defaultBaseUrl) + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const credentials = credentialData?.accessToken + + const params: any = { + credentials, + model: modelName, + scope, + profanityCheck: false, + timeout, + verbose: false, + streaming: true, + temperature, + baseUrl + } + + const model = new FlowiseGigaChat(params.model, params) + + return model + } +} + +module.exports = { nodeClass: ChatGigaChat } \ No newline at end of file diff --git a/packages/components/nodes/chatmodels/ChatGigaChat/FlowiseChatGigaChat.ts b/packages/components/nodes/chatmodels/ChatGigaChat/FlowiseChatGigaChat.ts new file mode 100644 index 00000000000..0b42613948f --- /dev/null +++ b/packages/components/nodes/chatmodels/ChatGigaChat/FlowiseChatGigaChat.ts @@ -0,0 +1,31 @@ +import { ChatOpenAIFields } from '@langchain/openai' +import { GigaChat as LangchainGigaChat } from 'langchain-gigachat' + +import { IMultiModalOption, IVisionChatModal } from '../../../src' + +export class FlowiseGigaChat extends LangchainGigaChat implements IVisionChatModal { + configuredModel: string + configuredMaxToken?: number + multiModalOption: IMultiModalOption + id: string + + constructor(id: string, fields?: ChatOpenAIFields) { + super(fields) + this.id = id + this.configuredModel = fields?.modelName ?? '' + this.configuredMaxToken = fields?.maxTokens + } + + revertToOriginalModel(): void { + this.model = this.configuredModel + this.maxTokens = this.configuredMaxToken + } + + setMultiModalOption(multiModalOption: IMultiModalOption): void { + this.multiModalOption = multiModalOption + } + + setVisionModel(): void { + // pass + } +} \ No newline at end of file diff --git a/packages/components/nodes/chatmodels/ChatGigaChat/GigaChat.svg b/packages/components/nodes/chatmodels/ChatGigaChat/GigaChat.svg new file mode 100644 index 00000000000..70a4a290d4c --- /dev/null +++ b/packages/components/nodes/chatmodels/ChatGigaChat/GigaChat.svg @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChat.svg b/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChat.svg new file mode 100644 index 00000000000..70a4a290d4c --- /dev/null +++ b/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChat.svg @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChatEmbedding.ts b/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChatEmbedding.ts new file mode 100644 index 00000000000..d8e7758967a --- /dev/null +++ b/packages/components/nodes/embeddings/GigaChatEmbedding/GigaChatEmbedding.ts @@ -0,0 +1,127 @@ +import https from 'node:https' +import { GigaChatEmbeddings as GCEmbeddings } from 'langchain-gigachat' + + +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, getCredentialData } from '../../../src/utils' + +const defaultBaseUrl = 'https://gigachat.devices.sberbank.ru/api/v1/' +class GigaChatEmbedding implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + credential: INodeParams + inputs: INodeParams[] + + constructor() { + this.label = 'GigaChatEmbedding' + this.name = 'gigachatembedding' + this.version = 2.0 + this.type = 'GigaChatEmbedding' + this.icon = 'GigaChat.svg' + this.category = 'Embeddings' + this.description = 'Wrapper around GigaChat large language models' + this.baseClasses = [this.type, 'BaseEmbedding_LlamaIndex', ...getBaseClasses(GCEmbeddings)] + this.credential = { + label: 'Credential', + name: 'credential', + type: 'credential', + credentialNames: ['gigaChatApi'] + } + this.inputs = [ + { + label: 'Model Name', + name: 'modelName', + type: 'options', + options: [ + { + label: 'Embeddings', + name: 'Embeddings', + description: 'basic model, available by default for vector representation of texts' + }, + { + label: 'Embeddings 2', + name: 'Embeddings-2', + description: 'an improved model with better quality embeddings' + }, + { + label: 'EmbeddingsGigaR', + name: 'EmbeddingsGigaR', + description: 'an advanced model with a large context' + } + ], + default: 'Embeddings' + }, + { + label: 'Scope', + name: 'scope', + type: 'options', + description: 'a required field in the request body that indicates which API version the request is being made to', + options: [ + { + label: 'GIGACHAT_API_PERS', + name: 'GIGACHAT_API_PERS', + description: 'personal access for individuals' + }, + { + label: 'GIGACHAT_API_B2B', + name: 'GIGACHAT_API_B2B', + description: 'business access for self-employed individuals' + }, + { + label: 'GIGACHAT_API_CORP', + name: 'GIGACHAT_API_CORP', + description: 'for corporate clients pay-as-you-go' + } + ], + default: 'GIGACHAT_API_PERS' + }, + { + label: 'Base URL', + name: 'baseUrl', + type: 'string', + default:defaultBaseUrl, + description: 'API URL', + optional: false + }, + { + label: 'Timeout', + name: 'timeout', + type: 'number', + step: 1, + default: 60000, + optional: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const timeout = Number(nodeData.inputs?.timeout || 60000) + const baseUrl = String(nodeData.inputs?.baseUrl || defaultBaseUrl) + const scope = String(nodeData.inputs?.scope || 'GIGACHAT_API_PERS') + const modelName = nodeData.inputs?.modelName as string + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const credentials = credentialData?.accessToken + + const params: any = { + credentials, + scope, + timeout, + verbose: false, + baseUrl, + model: modelName + } + + const model = new GCEmbeddings(params) + + return model + } +} + +module.exports = { nodeClass: GigaChatEmbedding } \ No newline at end of file diff --git a/packages/components/nodes/llms/GigaChat/GigaChat.svg b/packages/components/nodes/llms/GigaChat/GigaChat.svg new file mode 100644 index 00000000000..70a4a290d4c --- /dev/null +++ b/packages/components/nodes/llms/GigaChat/GigaChat.svg @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/packages/components/nodes/llms/GigaChat/GigaChat.ts b/packages/components/nodes/llms/GigaChat/GigaChat.ts new file mode 100644 index 00000000000..266f55c0390 --- /dev/null +++ b/packages/components/nodes/llms/GigaChat/GigaChat.ts @@ -0,0 +1,160 @@ +import { GigaChat as GigaChatInstance } from 'langchain-gigachat' + +import { getBaseClasses, getCredentialData } from '../../../src/utils' +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' + +const defaultBaseUrl = 'https://gigachat.devices.sberbank.ru/api/v1/' + +class GigaChat implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + credential: INodeParams + inputs: INodeParams[] + + constructor() { + this.label = 'GigaChat' + this.name = 'gigachat' + this.version = 2.0 + this.type = 'GigaChat' + this.icon = 'GigaChat.svg' + this.category = 'LLMs' + this.description = 'Wrapper around GigaChat large language models' + this.baseClasses = [this.type, ...getBaseClasses(GigaChatInstance)] + this.credential = { + label: 'Credential', + name: 'credential', + type: 'credential', + credentialNames: ['gigaChatApi'] + } + this.inputs = [ + { + label: 'Model Name', + name: 'modelName', + type: 'options', + options: [ + { + label: 'GigaChat v2', + name: 'GigaChat-2', + description: 'The most advanced model' + }, + { + label: 'GigaChat Pro v2', + name: 'GigaChat-2-Pro', + description: 'The most advanced model Pro' + }, + { + label: 'GigaChat Max v2', + name: 'GigaChat-2-Max', + description: 'The most advanced model Max' + }, + { + label: 'GigaChat Max', + name: 'GigaChat-Max', + description: 'An advanced model for complex tasks that require a high level of creativity and quality of work' + }, + { + label: 'GigaChat Pro', + name: 'GigaChat-Pro', + description: + 'the model follows complex instructions more effectively and can handle more sophisticated tasks: the quality of summarization, rewriting and editing texts, and answering various questions has improved significantly' + }, + { + label: 'GigaChat Plus', + name: 'GigaChat-Plus', + description: 'Ideally suited for tasks that require sending a large amount of information in a single request.' + }, + { + label: 'GigaChat', + name: 'GigaChat', + description: + 'Suitable for solving simpler tasks that require maximum processing speed. At the same time, the cost of using the model is lower because it requires fewer computational resources.' + } + ], + default: 'GigaChat-2-Pro' + }, + { + label: 'Scope', + name: 'scope', + type: 'options', + description: 'a required field in the request body that specifies which API version the request is being made to', + options: [ + { + label: 'GIGACHAT_API_PERS', + name: 'GIGACHAT_API_PERS', + description: 'access for individuals' + }, + { + label: 'GIGACHAT_API_B2B', + name: 'GIGACHAT_API_B2B', + description: 'access for sole proprietors and legal entities through paid packages' + }, + { + label: 'GIGACHAT_API_CORP', + name: 'GIGACHAT_API_CORP', + description: 'access for sole proprietors and legal entities on a pay-as-you-go basis' + } + ], + default: 'GIGACHAT_API_PERS' + }, + { + label: 'Base URL', + name: 'baseUrl', + type: 'string', + default: defaultBaseUrl, + description: 'API URL', + optional: false + }, + { + label: 'Temperature', + name: 'temperature', + type: 'number', + step: 0.1, + default: 1, + optional: true + }, + { + label: 'Timeout', + name: 'timeout', + type: 'number', + step: 1, + default: 60000, + optional: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const temperature = Number(nodeData.inputs?.temperature || 1) + const scope = String(nodeData.inputs?.scope || 'GIGACHAT_API_PERS') + const modelName = nodeData.inputs?.modelName as string + const timeout = Number(nodeData.inputs?.timeout || 60000) + const baseUrl = String(nodeData.inputs?.baseUrl || defaultBaseUrl) + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const credentials = credentialData?.accessToken + + const params: any = { + credentials, + model: modelName, + scope, + profanityCheck: false, + timeout, + verbose: false, + streaming: true, + temperature, + baseUrl + } + + const model = new GigaChatInstance(params) + + return model + } +} + +module.exports = { nodeClass: GigaChat } diff --git a/packages/components/package.json b/packages/components/package.json index f3894f996c4..92d20a533a8 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -110,6 +110,7 @@ "jsonpointer": "^5.0.1", "jsonrepair": "^3.11.1", "langchain": "^0.3.5", + "langchain-gigachat": "^0.0.14", "langfuse": "3.3.4", "langfuse-langchain": "^3.3.4", "langsmith": "0.1.6", diff --git a/packages/server/.env.example b/packages/server/.env.example index 282e4cd33fc..69d2eaef125 100644 --- a/packages/server/.env.example +++ b/packages/server/.env.example @@ -186,3 +186,6 @@ JWT_REFRESH_TOKEN_EXPIRY_IN_MINUTES=43200 # PUPPETEER_EXECUTABLE_FILE_PATH='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' # PLAYWRIGHT_EXECUTABLE_FILE_PATH='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe' + +# To use GigaChat, you need to allow self-signed certificates +# NODE_TLS_REJECT_UNAUTHORIZED=0 \ No newline at end of file