From fc392859cf2a8911e737ec093990a5413e0bd0be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 22:49:50 +0000 Subject: [PATCH 1/5] Initial plan From 1fbd4e2378a8270c442230ed233c476606a7a58d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 22:56:08 +0000 Subject: [PATCH 2/5] Add AI Badgr provider with chat model and embeddings support Co-authored-by: miguelmanlyx <220451577+miguelmanlyx@users.noreply.github.com> --- .../credentials/AIBadgrApi.credential.ts | 23 +++++ .../chatmodels/ChatAIBadgr/ChatAIBadgr.ts | 90 ++++++++++++++++++ .../nodes/chatmodels/ChatAIBadgr/aibadgr.png | Bin 0 -> 1598 bytes .../AIBadgrEmbedding/AIBadgrEmbedding.ts | 68 +++++++++++++ .../embeddings/AIBadgrEmbedding/aibadgr.png | Bin 0 -> 1598 bytes 5 files changed, 181 insertions(+) create mode 100644 packages/components/credentials/AIBadgrApi.credential.ts create mode 100644 packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts create mode 100644 packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png create mode 100644 packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts create mode 100644 packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png diff --git a/packages/components/credentials/AIBadgrApi.credential.ts b/packages/components/credentials/AIBadgrApi.credential.ts new file mode 100644 index 00000000000..3f1842ed3fe --- /dev/null +++ b/packages/components/credentials/AIBadgrApi.credential.ts @@ -0,0 +1,23 @@ +import { INodeParams, INodeCredential } from '../src/Interface' + +class AIBadgrApi implements INodeCredential { + label: string + name: string + version: number + inputs: INodeParams[] + + constructor() { + this.label = 'AI Badgr API' + this.name = 'aiBadgrApi' + this.version = 1.0 + this.inputs = [ + { + label: 'AI Badgr Api Key', + name: 'aiBadgrApiKey', + type: 'password' + } + ] + } +} + +module.exports = { credClass: AIBadgrApi } diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts new file mode 100644 index 00000000000..084de77e5e5 --- /dev/null +++ b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts @@ -0,0 +1,90 @@ +import { BaseCache } from '@langchain/core/caches' +import { ChatOpenAI } from '@langchain/openai' +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' + +class ChatAIBadgr_ChatModels implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + inputs: INodeParams[] + credential: INodeParams + + constructor() { + this.label = 'ChatAIBadgr' + this.name = 'chatAIBadgr' + this.version = 1.0 + this.type = 'ChatAIBadgr' + this.icon = 'aibadgr.png' + this.category = 'Chat Models' + this.description = 'Wrapper around AI Badgr large language models' + this.baseClasses = [this.type, ...getBaseClasses(ChatOpenAI)] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['aiBadgrApi'] + } + this.inputs = [ + { + label: 'Cache', + name: 'cache', + type: 'BaseCache', + optional: true + }, + { + label: 'Model Name', + name: 'modelName', + type: 'string', + placeholder: 'gpt-4o', + description: 'Refer to models page' + }, + { + label: 'Temperature', + name: 'temperature', + type: 'number', + step: 0.1, + default: 0.9, + optional: true + }, + { + label: 'Streaming', + name: 'streaming', + type: 'boolean', + default: true, + optional: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const modelName = nodeData.inputs?.modelName as string + const cache = nodeData.inputs?.cache as BaseCache + const temperature = nodeData.inputs?.temperature as string + const streaming = nodeData.inputs?.streaming as boolean + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const aiBadgrApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + + const obj: any = { + model: modelName, + temperature: parseFloat(temperature), + openAIApiKey: aiBadgrApiKey, + streaming: streaming ?? true, + configuration: { + baseURL: 'https://aibadgr.com/api/v1' + } + } + if (cache) obj.cache = cache + + const model = new ChatOpenAI(obj) + return model + } +} + +module.exports = { nodeClass: ChatAIBadgr_ChatModels } diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png b/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png new file mode 100644 index 0000000000000000000000000000000000000000..371103f6f83cc8a3efe7784ae7e0177ca5f245c7 GIT binary patch literal 1598 zcmZ{kc~DbV6vkgL88k?100UUjq5&i8V~@D72*!ZHfJh^V21vqE!lFS)2n>`>l)`|> zAZT%o0u}*T98^Rck%AjZ-pflOpeQP+KvWD3Tc38OGo4On?!Di9=iJ|%`R*ULkP$%D z$FITz0H9CX=@W!%1-eU@E@BS0H8%nS#JR#1q6U`7675jlHXk&=6E7%uR1cqU$6qZR9FsxE2V3|y*KooLVIxv91kZfQ;4#^;?R3?!i z5CqAjDg=?EcjR)JRH{UfXD9+eDg^>bBuXX9!OxTmguy|Xdrk82^l~dH>S$54#r&Rqz%0iM@ zv003)4 z^YIE!Q+}vc2uHx>dD)&_<(07=UgxA4iDR9Uv$qxv>0vQ6n@w%;A6t#Ji56#0Q!qv6 zjquCwf#`a;n_+_+y_#mRyxT9tds8p*O2u)P^Ou`V7;=*6exBt4x23_IBT?9&)?tW= zq!E4NY%-z!fTMXcCntEzS-sxiTW?43eXb|dPFPJ*3rkctj_rlIl7gojOTEs<88n94 zwANup^sBP4YVO^oTZ|ndC~?|G!%iJC!KRF~cg&h4&_8KaK%oO110uaF_%@CqW(^q8 zps=nlR^pdauaC#*fC-=S@Cp0&fxQMeaX7Jm&ce(}ZCdB~#ii{t=ko{a6)SBVY#Y^h z#t7Unlvr|i-rQnMV(aX(=D|aTS6XLH%bJIU(QQW9ONydg?nbgp2G)HtxqqwvxBU24 z;l^WrDH*EsCi#IT#7~A@ew~_kgagKzydq9z39zGXeU39b=w`~P0wDjR+_KN;KKnKf z3?28#3K5gbr-`0~EdJ`YZI(N1p0oX*8Xna#F=NWiYlV7DJNVjLWG*OdDEzuenGnvD zxvUN;4*8bLcZGd16W|2cR_!rZuu|W-K+>*JAYb=BseL?vZGbg9j!*!X!W95GPi^;Rs@7b@ji3@mIMdSvM$aFN9$?*Y-A7 zH(0(J$LOqK$0@hmb6uj%jZcqmcVneStGs}NwXcQBh@4;q8_lchLDk90GS zQh6f5D0|z$-3a^pFED`sb^hh~9w-_b&)YV>aWw(Q=<>`Kx~@}c)P-^HUR9DZe{Q>;o&nXZ}DIq z3G$D5CmF8LY*6Es9qX1oPuoojuWx85)CuYIob*1kd2cn>tuI*tg}q}J$&&^*0Zm zgEAy$Mb`aS3l8R-i>3)YcMLrpKbErniQNT{p5#>TWOiwk0DIX3I9OgD`F=3Ll^ zQOLCPxy4gV6FYNPJ$b~nKNBYspxCU zbm$ZOE{hy=Z!z4&OCKZ8#$W$ali@SZf|J;>zn$Gr-i7tXx=OE;ow{$?&!l-&KUGDd zala;B`_e=FMA8_#${hV}0Smq_lh2OebKIj2aZmvqK}Tm>(8U&X4t8*J2OZpac$SyhL^^SMdLU07rX+0_1-t@MC$L!~6(d(tjCer@x0-N?cSZ1JHZ}d>Xu2 Gzx)LY`}5`i literal 0 HcmV?d00001 diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts new file mode 100644 index 00000000000..c8130c7d7c8 --- /dev/null +++ b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts @@ -0,0 +1,68 @@ +import { OpenAIEmbeddings, OpenAIEmbeddingsParams } from '@langchain/openai' +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' + +class AIBadgrEmbedding_Embeddings implements INode { + label: string + name: string + version: number + type: string + icon: string + category: string + description: string + baseClasses: string[] + inputs: INodeParams[] + credential: INodeParams + + constructor() { + this.label = 'AIBadgrEmbedding' + this.name = 'aiBadgrEmbedding' + this.version = 1.0 + this.type = 'AIBadgrEmbedding' + this.icon = 'aibadgr.png' + this.category = 'Embeddings' + this.description = 'AI Badgr Embedding models to generate embeddings for a given text' + this.baseClasses = [this.type, ...getBaseClasses(OpenAIEmbeddings)] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['aiBadgrApi'] + } + this.inputs = [ + { + label: 'Cache', + name: 'cache', + type: 'BaseCache', + optional: true + }, + { + label: 'Model Name', + name: 'modelName', + type: 'string', + placeholder: 'text-embedding-3-small', + description: 'Refer to embedding models page' + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const modelName = nodeData.inputs?.modelName as string + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const aiBadgrApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + + const obj: Partial = { + modelName: modelName, + openAIApiKey: aiBadgrApiKey, + configuration: { + baseURL: 'https://aibadgr.com/api/v1' + } + } + + const model = new OpenAIEmbeddings(obj) + return model + } +} + +module.exports = { nodeClass: AIBadgrEmbedding_Embeddings } diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png b/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png new file mode 100644 index 0000000000000000000000000000000000000000..371103f6f83cc8a3efe7784ae7e0177ca5f245c7 GIT binary patch literal 1598 zcmZ{kc~DbV6vkgL88k?100UUjq5&i8V~@D72*!ZHfJh^V21vqE!lFS)2n>`>l)`|> zAZT%o0u}*T98^Rck%AjZ-pflOpeQP+KvWD3Tc38OGo4On?!Di9=iJ|%`R*ULkP$%D z$FITz0H9CX=@W!%1-eU@E@BS0H8%nS#JR#1q6U`7675jlHXk&=6E7%uR1cqU$6qZR9FsxE2V3|y*KooLVIxv91kZfQ;4#^;?R3?!i z5CqAjDg=?EcjR)JRH{UfXD9+eDg^>bBuXX9!OxTmguy|Xdrk82^l~dH>S$54#r&Rqz%0iM@ zv003)4 z^YIE!Q+}vc2uHx>dD)&_<(07=UgxA4iDR9Uv$qxv>0vQ6n@w%;A6t#Ji56#0Q!qv6 zjquCwf#`a;n_+_+y_#mRyxT9tds8p*O2u)P^Ou`V7;=*6exBt4x23_IBT?9&)?tW= zq!E4NY%-z!fTMXcCntEzS-sxiTW?43eXb|dPFPJ*3rkctj_rlIl7gojOTEs<88n94 zwANup^sBP4YVO^oTZ|ndC~?|G!%iJC!KRF~cg&h4&_8KaK%oO110uaF_%@CqW(^q8 zps=nlR^pdauaC#*fC-=S@Cp0&fxQMeaX7Jm&ce(}ZCdB~#ii{t=ko{a6)SBVY#Y^h z#t7Unlvr|i-rQnMV(aX(=D|aTS6XLH%bJIU(QQW9ONydg?nbgp2G)HtxqqwvxBU24 z;l^WrDH*EsCi#IT#7~A@ew~_kgagKzydq9z39zGXeU39b=w`~P0wDjR+_KN;KKnKf z3?28#3K5gbr-`0~EdJ`YZI(N1p0oX*8Xna#F=NWiYlV7DJNVjLWG*OdDEzuenGnvD zxvUN;4*8bLcZGd16W|2cR_!rZuu|W-K+>*JAYb=BseL?vZGbg9j!*!X!W95GPi^;Rs@7b@ji3@mIMdSvM$aFN9$?*Y-A7 zH(0(J$LOqK$0@hmb6uj%jZcqmcVneStGs}NwXcQBh@4;q8_lchLDk90GS zQh6f5D0|z$-3a^pFED`sb^hh~9w-_b&)YV>aWw(Q=<>`Kx~@}c)P-^HUR9DZe{Q>;o&nXZ}DIq z3G$D5CmF8LY*6Es9qX1oPuoojuWx85)CuYIob*1kd2cn>tuI*tg}q}J$&&^*0Zm zgEAy$Mb`aS3l8R-i>3)YcMLrpKbErniQNT{p5#>TWOiwk0DIX3I9OgD`F=3Ll^ zQOLCPxy4gV6FYNPJ$b~nKNBYspxCU zbm$ZOE{hy=Z!z4&OCKZ8#$W$ali@SZf|J;>zn$Gr-i7tXx=OE;ow{$?&!l-&KUGDd zala;B`_e=FMA8_#${hV}0Smq_lh2OebKIj2aZmvqK}Tm>(8U&X4t8*J2OZpac$SyhL^^SMdLU07rX+0_1-t@MC$L!~6(d(tjCer@x0-N?cSZ1JHZ}d>Xu2 Gzx)LY`}5`i literal 0 HcmV?d00001 From 000c515da757ed3a9167e9cc8e8fcbf6eff17dfa Mon Sep 17 00:00:00 2001 From: miguelmanlyx Date: Thu, 18 Dec 2025 13:53:21 +1000 Subject: [PATCH 3/5] Aibadgr SVG --- .../chatmodels/ChatAIBadgr/ChatAIBadgr.ts | 2 +- .../nodes/chatmodels/ChatAIBadgr/aibadgr.png | Bin 1598 -> 0 bytes .../nodes/chatmodels/ChatAIBadgr/aibadgr.svg | 174 ++++++++++++++++++ .../AIBadgrEmbedding/AIBadgrEmbedding.ts | 2 +- .../embeddings/AIBadgrEmbedding/aibadgr.png | Bin 1598 -> 0 bytes .../embeddings/AIBadgrEmbedding/aibadgr.svg | 174 ++++++++++++++++++ 6 files changed, 350 insertions(+), 2 deletions(-) delete mode 100644 packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png create mode 100644 packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.svg delete mode 100644 packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png create mode 100644 packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.svg diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts index 084de77e5e5..b64071d6a90 100644 --- a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts +++ b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts @@ -20,7 +20,7 @@ class ChatAIBadgr_ChatModels implements INode { this.name = 'chatAIBadgr' this.version = 1.0 this.type = 'ChatAIBadgr' - this.icon = 'aibadgr.png' + this.icon = 'aibadgr.svg' this.category = 'Chat Models' this.description = 'Wrapper around AI Badgr large language models' this.baseClasses = [this.type, ...getBaseClasses(ChatOpenAI)] diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png b/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.png deleted file mode 100644 index 371103f6f83cc8a3efe7784ae7e0177ca5f245c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1598 zcmZ{kc~DbV6vkgL88k?100UUjq5&i8V~@D72*!ZHfJh^V21vqE!lFS)2n>`>l)`|> zAZT%o0u}*T98^Rck%AjZ-pflOpeQP+KvWD3Tc38OGo4On?!Di9=iJ|%`R*ULkP$%D z$FITz0H9CX=@W!%1-eU@E@BS0H8%nS#JR#1q6U`7675jlHXk&=6E7%uR1cqU$6qZR9FsxE2V3|y*KooLVIxv91kZfQ;4#^;?R3?!i z5CqAjDg=?EcjR)JRH{UfXD9+eDg^>bBuXX9!OxTmguy|Xdrk82^l~dH>S$54#r&Rqz%0iM@ zv003)4 z^YIE!Q+}vc2uHx>dD)&_<(07=UgxA4iDR9Uv$qxv>0vQ6n@w%;A6t#Ji56#0Q!qv6 zjquCwf#`a;n_+_+y_#mRyxT9tds8p*O2u)P^Ou`V7;=*6exBt4x23_IBT?9&)?tW= zq!E4NY%-z!fTMXcCntEzS-sxiTW?43eXb|dPFPJ*3rkctj_rlIl7gojOTEs<88n94 zwANup^sBP4YVO^oTZ|ndC~?|G!%iJC!KRF~cg&h4&_8KaK%oO110uaF_%@CqW(^q8 zps=nlR^pdauaC#*fC-=S@Cp0&fxQMeaX7Jm&ce(}ZCdB~#ii{t=ko{a6)SBVY#Y^h z#t7Unlvr|i-rQnMV(aX(=D|aTS6XLH%bJIU(QQW9ONydg?nbgp2G)HtxqqwvxBU24 z;l^WrDH*EsCi#IT#7~A@ew~_kgagKzydq9z39zGXeU39b=w`~P0wDjR+_KN;KKnKf z3?28#3K5gbr-`0~EdJ`YZI(N1p0oX*8Xna#F=NWiYlV7DJNVjLWG*OdDEzuenGnvD zxvUN;4*8bLcZGd16W|2cR_!rZuu|W-K+>*JAYb=BseL?vZGbg9j!*!X!W95GPi^;Rs@7b@ji3@mIMdSvM$aFN9$?*Y-A7 zH(0(J$LOqK$0@hmb6uj%jZcqmcVneStGs}NwXcQBh@4;q8_lchLDk90GS zQh6f5D0|z$-3a^pFED`sb^hh~9w-_b&)YV>aWw(Q=<>`Kx~@}c)P-^HUR9DZe{Q>;o&nXZ}DIq z3G$D5CmF8LY*6Es9qX1oPuoojuWx85)CuYIob*1kd2cn>tuI*tg}q}J$&&^*0Zm zgEAy$Mb`aS3l8R-i>3)YcMLrpKbErniQNT{p5#>TWOiwk0DIX3I9OgD`F=3Ll^ zQOLCPxy4gV6FYNPJ$b~nKNBYspxCU zbm$ZOE{hy=Z!z4&OCKZ8#$W$ali@SZf|J;>zn$Gr-i7tXx=OE;ow{$?&!l-&KUGDd zala;B`_e=FMA8_#${hV}0Smq_lh2OebKIj2aZmvqK}Tm>(8U&X4t8*J2OZpac$SyhL^^SMdLU07rX+0_1-t@MC$L!~6(d(tjCer@x0-N?cSZ1JHZ}d>Xu2 Gzx)LY`}5`i diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.svg b/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.svg new file mode 100644 index 00000000000..163df36aed0 --- /dev/null +++ b/packages/components/nodes/chatmodels/ChatAIBadgr/aibadgr.svg @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts index c8130c7d7c8..8f7acb007dd 100644 --- a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts +++ b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts @@ -19,7 +19,7 @@ class AIBadgrEmbedding_Embeddings implements INode { this.name = 'aiBadgrEmbedding' this.version = 1.0 this.type = 'AIBadgrEmbedding' - this.icon = 'aibadgr.png' + this.icon = 'aibadgr.svg' this.category = 'Embeddings' this.description = 'AI Badgr Embedding models to generate embeddings for a given text' this.baseClasses = [this.type, ...getBaseClasses(OpenAIEmbeddings)] diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png b/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.png deleted file mode 100644 index 371103f6f83cc8a3efe7784ae7e0177ca5f245c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1598 zcmZ{kc~DbV6vkgL88k?100UUjq5&i8V~@D72*!ZHfJh^V21vqE!lFS)2n>`>l)`|> zAZT%o0u}*T98^Rck%AjZ-pflOpeQP+KvWD3Tc38OGo4On?!Di9=iJ|%`R*ULkP$%D z$FITz0H9CX=@W!%1-eU@E@BS0H8%nS#JR#1q6U`7675jlHXk&=6E7%uR1cqU$6qZR9FsxE2V3|y*KooLVIxv91kZfQ;4#^;?R3?!i z5CqAjDg=?EcjR)JRH{UfXD9+eDg^>bBuXX9!OxTmguy|Xdrk82^l~dH>S$54#r&Rqz%0iM@ zv003)4 z^YIE!Q+}vc2uHx>dD)&_<(07=UgxA4iDR9Uv$qxv>0vQ6n@w%;A6t#Ji56#0Q!qv6 zjquCwf#`a;n_+_+y_#mRyxT9tds8p*O2u)P^Ou`V7;=*6exBt4x23_IBT?9&)?tW= zq!E4NY%-z!fTMXcCntEzS-sxiTW?43eXb|dPFPJ*3rkctj_rlIl7gojOTEs<88n94 zwANup^sBP4YVO^oTZ|ndC~?|G!%iJC!KRF~cg&h4&_8KaK%oO110uaF_%@CqW(^q8 zps=nlR^pdauaC#*fC-=S@Cp0&fxQMeaX7Jm&ce(}ZCdB~#ii{t=ko{a6)SBVY#Y^h z#t7Unlvr|i-rQnMV(aX(=D|aTS6XLH%bJIU(QQW9ONydg?nbgp2G)HtxqqwvxBU24 z;l^WrDH*EsCi#IT#7~A@ew~_kgagKzydq9z39zGXeU39b=w`~P0wDjR+_KN;KKnKf z3?28#3K5gbr-`0~EdJ`YZI(N1p0oX*8Xna#F=NWiYlV7DJNVjLWG*OdDEzuenGnvD zxvUN;4*8bLcZGd16W|2cR_!rZuu|W-K+>*JAYb=BseL?vZGbg9j!*!X!W95GPi^;Rs@7b@ji3@mIMdSvM$aFN9$?*Y-A7 zH(0(J$LOqK$0@hmb6uj%jZcqmcVneStGs}NwXcQBh@4;q8_lchLDk90GS zQh6f5D0|z$-3a^pFED`sb^hh~9w-_b&)YV>aWw(Q=<>`Kx~@}c)P-^HUR9DZe{Q>;o&nXZ}DIq z3G$D5CmF8LY*6Es9qX1oPuoojuWx85)CuYIob*1kd2cn>tuI*tg}q}J$&&^*0Zm zgEAy$Mb`aS3l8R-i>3)YcMLrpKbErniQNT{p5#>TWOiwk0DIX3I9OgD`F=3Ll^ zQOLCPxy4gV6FYNPJ$b~nKNBYspxCU zbm$ZOE{hy=Z!z4&OCKZ8#$W$ali@SZf|J;>zn$Gr-i7tXx=OE;ow{$?&!l-&KUGDd zala;B`_e=FMA8_#${hV}0Smq_lh2OebKIj2aZmvqK}Tm>(8U&X4t8*J2OZpac$SyhL^^SMdLU07rX+0_1-t@MC$L!~6(d(tjCer@x0-N?cSZ1JHZ}d>Xu2 Gzx)LY`}5`i diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.svg b/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.svg new file mode 100644 index 00000000000..163df36aed0 --- /dev/null +++ b/packages/components/nodes/embeddings/AIBadgrEmbedding/aibadgr.svg @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 45219ae6f71b17c4f6eb0d2c8502e0b5607cf2cb Mon Sep 17 00:00:00 2001 From: michaelmanley <55236695+michaelbrinkworth@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:02:25 +1000 Subject: [PATCH 4/5] update base url --- .../chatmodels/ChatAIBadgr/ChatAIBadgr.ts | 120 +++++++++++++++--- .../AIBadgrEmbedding/AIBadgrEmbedding.ts | 82 +++++++++--- 2 files changed, 169 insertions(+), 33 deletions(-) diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts index b64071d6a90..bddadafd543 100644 --- a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts +++ b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts @@ -1,9 +1,10 @@ import { BaseCache } from '@langchain/core/caches' -import { ChatOpenAI } from '@langchain/openai' +import { ChatOpenAI, ChatOpenAIFields } from '@langchain/openai' import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' class ChatAIBadgr_ChatModels implements INode { + readonly baseURL: string = 'https://aibadgr.com/api/v1' label: string name: string version: number @@ -12,8 +13,8 @@ class ChatAIBadgr_ChatModels implements INode { category: string description: string baseClasses: string[] - inputs: INodeParams[] credential: INodeParams + inputs: INodeParams[] constructor() { this.label = 'ChatAIBadgr' @@ -22,7 +23,7 @@ class ChatAIBadgr_ChatModels implements INode { this.type = 'ChatAIBadgr' this.icon = 'aibadgr.svg' this.category = 'Chat Models' - this.description = 'Wrapper around AI Badgr large language models' + this.description = 'Wrapper around AI Badgr large language models that use the Chat endpoint' this.baseClasses = [this.type, ...getBaseClasses(ChatOpenAI)] this.credential = { label: 'Connect Credential', @@ -41,7 +42,7 @@ class ChatAIBadgr_ChatModels implements INode { label: 'Model Name', name: 'modelName', type: 'string', - placeholder: 'gpt-4o', + default: 'gpt-4o', description: 'Refer to models page' }, { @@ -49,7 +50,7 @@ class ChatAIBadgr_ChatModels implements INode { name: 'temperature', type: 'number', step: 0.1, - default: 0.9, + default: 0.7, optional: true }, { @@ -57,32 +58,117 @@ class ChatAIBadgr_ChatModels implements INode { name: 'streaming', type: 'boolean', default: true, - optional: true + optional: true, + additionalParams: true + }, + { + label: 'Max Tokens', + name: 'maxTokens', + type: 'number', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Top Probability', + name: 'topP', + type: 'number', + step: 0.1, + optional: true, + additionalParams: true + }, + { + label: 'Frequency Penalty', + name: 'frequencyPenalty', + type: 'number', + step: 0.1, + optional: true, + additionalParams: true + }, + { + label: 'Presence Penalty', + name: 'presencePenalty', + type: 'number', + step: 0.1, + optional: true, + additionalParams: true + }, + { + label: 'Base Options', + name: 'baseOptions', + type: 'json', + optional: true, + additionalParams: true, + description: 'Additional options to pass to the AI Badgr client. This should be a JSON object.' } ] } async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { - const modelName = nodeData.inputs?.modelName as string - const cache = nodeData.inputs?.cache as BaseCache const temperature = nodeData.inputs?.temperature as string + const modelName = nodeData.inputs?.modelName as string + const maxTokens = nodeData.inputs?.maxTokens as string + const topP = nodeData.inputs?.topP as string + const frequencyPenalty = nodeData.inputs?.frequencyPenalty as string + const presencePenalty = nodeData.inputs?.presencePenalty as string const streaming = nodeData.inputs?.streaming as boolean + const baseOptions = nodeData.inputs?.baseOptions + if (nodeData.inputs?.credentialId) { + nodeData.credential = nodeData.inputs?.credentialId + } const credentialData = await getCredentialData(nodeData.credential ?? '', options) - const aiBadgrApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + const openAIApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + + // Custom error handling for missing API key + if (!openAIApiKey || openAIApiKey.trim() === '') { + throw new Error( + 'AI Badgr API Key is missing or empty. Please provide a valid AI Badgr API key in the credential configuration.' + ) + } + + // Custom error handling for missing model name + if (!modelName || modelName.trim() === '') { + throw new Error('Model Name is required. Please enter a valid model name (e.g., gpt-4o).') + } + + const cache = nodeData.inputs?.cache as BaseCache - const obj: any = { - model: modelName, + const obj: ChatOpenAIFields = { temperature: parseFloat(temperature), - openAIApiKey: aiBadgrApiKey, - streaming: streaming ?? true, - configuration: { - baseURL: 'https://aibadgr.com/api/v1' - } + modelName, + openAIApiKey, + apiKey: openAIApiKey, + streaming: streaming ?? true } + + if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10) + if (topP) obj.topP = parseFloat(topP) + if (frequencyPenalty) obj.frequencyPenalty = parseFloat(frequencyPenalty) + if (presencePenalty) obj.presencePenalty = parseFloat(presencePenalty) if (cache) obj.cache = cache - const model = new ChatOpenAI(obj) + let parsedBaseOptions: any | undefined = undefined + + if (baseOptions) { + try { + parsedBaseOptions = typeof baseOptions === 'object' ? baseOptions : JSON.parse(baseOptions) + if (parsedBaseOptions.baseURL) { + console.warn("The 'baseURL' parameter is not allowed when using the ChatAIBadgr node.") + parsedBaseOptions.baseURL = undefined + } + } catch (exception) { + throw new Error('Invalid JSON in the BaseOptions: ' + exception) + } + } + + const model = new ChatOpenAI({ + ...obj, + configuration: { + baseURL: this.baseURL, + ...parsedBaseOptions + } + }) return model } } diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts index 8f7acb007dd..c5cd946bc7b 100644 --- a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts +++ b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts @@ -1,8 +1,9 @@ -import { OpenAIEmbeddings, OpenAIEmbeddingsParams } from '@langchain/openai' +import { ClientOptions, OpenAIEmbeddings, OpenAIEmbeddingsParams } from '@langchain/openai' import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' class AIBadgrEmbedding_Embeddings implements INode { + readonly baseURL: string = 'https://aibadgr.com/api/v1' label: string name: string version: number @@ -11,17 +12,17 @@ class AIBadgrEmbedding_Embeddings implements INode { category: string description: string baseClasses: string[] - inputs: INodeParams[] credential: INodeParams + inputs: INodeParams[] constructor() { this.label = 'AIBadgrEmbedding' this.name = 'aiBadgrEmbedding' - this.version = 1.0 + this.version = 3.0 this.type = 'AIBadgrEmbedding' this.icon = 'aibadgr.svg' this.category = 'Embeddings' - this.description = 'AI Badgr Embedding models to generate embeddings for a given text' + this.description = 'AI Badgr API to generate embeddings for a given text' this.baseClasses = [this.type, ...getBaseClasses(OpenAIEmbeddings)] this.credential = { label: 'Connect Credential', @@ -31,35 +32,84 @@ class AIBadgrEmbedding_Embeddings implements INode { } this.inputs = [ { - label: 'Cache', - name: 'cache', - type: 'BaseCache', - optional: true + label: 'Strip New Lines', + name: 'stripNewLines', + type: 'boolean', + optional: true, + additionalParams: true + }, + { + label: 'Batch Size', + name: 'batchSize', + type: 'number', + optional: true, + additionalParams: true + }, + { + label: 'Timeout', + name: 'timeout', + type: 'number', + optional: true, + additionalParams: true + }, + { + label: 'BaseOptions', + name: 'baseOptions', + type: 'json', + optional: true, + additionalParams: true }, { label: 'Model Name', name: 'modelName', type: 'string', - placeholder: 'text-embedding-3-small', - description: 'Refer to embedding models page' + optional: true + }, + { + label: 'Dimensions', + name: 'dimensions', + type: 'number', + optional: true, + additionalParams: true } ] } async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const stripNewLines = nodeData.inputs?.stripNewLines as boolean + const batchSize = nodeData.inputs?.batchSize as string + const timeout = nodeData.inputs?.timeout as string const modelName = nodeData.inputs?.modelName as string + const dimensions = nodeData.inputs?.dimensions as string + const baseOptions = nodeData.inputs?.baseOptions const credentialData = await getCredentialData(nodeData.credential ?? '', options) - const aiBadgrApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + const openAIApiKey = getCredentialParam('aiBadgrApiKey', credentialData, nodeData) + + const obj: Partial & { openAIApiKey?: string; configuration?: ClientOptions } = { + openAIApiKey + } + + if (stripNewLines) obj.stripNewLines = stripNewLines + if (batchSize) obj.batchSize = parseInt(batchSize, 10) + if (timeout) obj.timeout = parseInt(timeout, 10) + if (modelName) obj.modelName = modelName + if (dimensions) obj.dimensions = parseInt(dimensions, 10) - const obj: Partial = { - modelName: modelName, - openAIApiKey: aiBadgrApiKey, - configuration: { - baseURL: 'https://aibadgr.com/api/v1' + let parsedBaseOptions: any | undefined = undefined + if (baseOptions) { + try { + parsedBaseOptions = typeof baseOptions === 'object' ? baseOptions : JSON.parse(baseOptions) + } catch (exception) { + throw new Error("Invalid JSON in the AIBadgrEmbedding's BaseOptions: " + exception) } } + obj.configuration = { + baseURL: this.baseURL, + defaultHeaders: parsedBaseOptions + } + const model = new OpenAIEmbeddings(obj) return model } From f1c3adc7fe7a672deac30ad0750b64b365dc4de7 Mon Sep 17 00:00:00 2001 From: michaelmanley <55236695+michaelbrinkworth@users.noreply.github.com> Date: Thu, 18 Dec 2025 19:27:41 +1000 Subject: [PATCH 5/5] gemini feedback --- .../nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts | 2 +- .../embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts index bddadafd543..d4655c02988 100644 --- a/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts +++ b/packages/components/nodes/chatmodels/ChatAIBadgr/ChatAIBadgr.ts @@ -135,13 +135,13 @@ class ChatAIBadgr_ChatModels implements INode { const cache = nodeData.inputs?.cache as BaseCache const obj: ChatOpenAIFields = { - temperature: parseFloat(temperature), modelName, openAIApiKey, apiKey: openAIApiKey, streaming: streaming ?? true } + if (temperature) obj.temperature = parseFloat(temperature) if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10) if (topP) obj.topP = parseFloat(topP) if (frequencyPenalty) obj.frequencyPenalty = parseFloat(frequencyPenalty) diff --git a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts index c5cd946bc7b..289538ad868 100644 --- a/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts +++ b/packages/components/nodes/embeddings/AIBadgrEmbedding/AIBadgrEmbedding.ts @@ -57,7 +57,8 @@ class AIBadgrEmbedding_Embeddings implements INode { name: 'baseOptions', type: 'json', optional: true, - additionalParams: true + additionalParams: true, + description: 'Additional options to pass to the AI Badgr client. This should be a JSON object.' }, { label: 'Model Name', @@ -100,6 +101,10 @@ class AIBadgrEmbedding_Embeddings implements INode { if (baseOptions) { try { parsedBaseOptions = typeof baseOptions === 'object' ? baseOptions : JSON.parse(baseOptions) + if (parsedBaseOptions.baseURL) { + console.warn("The 'baseURL' parameter is not allowed when using the AIBadgrEmbedding node.") + parsedBaseOptions.baseURL = undefined + } } catch (exception) { throw new Error("Invalid JSON in the AIBadgrEmbedding's BaseOptions: " + exception) } @@ -107,7 +112,7 @@ class AIBadgrEmbedding_Embeddings implements INode { obj.configuration = { baseURL: this.baseURL, - defaultHeaders: parsedBaseOptions + ...(parsedBaseOptions ?? {}) } const model = new OpenAIEmbeddings(obj)