Files
Flowise/packages/components/nodes/embeddings/AWSBedrockEmbedding/AWSBedrockEmbedding.ts
T
Vinod Kiran 788d40f26b Feature/externalize model list (#2113)
* fixes

* test json

* test json

* externalize model list

* externalize model list

* correcting awsChatBedRock Name

* lint fixes

* externalize models

* externalize chat models

* externalize chat models

* externalize llm models

* externalize llm models

* lint fixes

* addition of models for ChatMistral

* updating version numbers for all imapacted nodes.

* marketplace template updates

* update embeddings, marketplaces, add chatCohere

* config changes for new env variable

* removal of local models.json

* update models json file

---------

Co-authored-by: Henry <hzj94@hotmail.com>
2024-04-12 12:46:10 +01:00

136 lines
4.8 KiB
TypeScript

import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime'
import { BedrockEmbeddings, BedrockEmbeddingsParams } from '@langchain/community/embeddings/bedrock'
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
import { MODEL_TYPE, getModels, getRegions } from '../../../src/modelLoader'
class AWSBedrockEmbedding_Embeddings 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 = 'AWS Bedrock Embeddings'
this.name = 'AWSBedrockEmbeddings'
this.version = 4.0
this.type = 'AWSBedrockEmbeddings'
this.icon = 'aws.svg'
this.category = 'Embeddings'
this.description = 'AWSBedrock embedding models to generate embeddings for a given text'
this.baseClasses = [this.type, ...getBaseClasses(BedrockEmbeddings)]
this.credential = {
label: 'AWS Credential',
name: 'credential',
type: 'credential',
credentialNames: ['awsApi'],
optional: true
}
this.inputs = [
{
label: 'Region',
name: 'region',
type: 'asyncOptions',
loadMethod: 'listRegions',
default: 'us-east-1'
},
{
label: 'Model Name',
name: 'model',
type: 'asyncOptions',
loadMethod: 'listModels',
default: 'amazon.titan-embed-text-v1'
},
{
label: 'Custom Model Name',
name: 'customModel',
description: 'If provided, will override model selected from Model Name option',
type: 'string',
optional: true
}
]
}
//@ts-ignore
loadMethods = {
async listModels(): Promise<INodeOptionsValue[]> {
return await getModels(MODEL_TYPE.EMBEDDING, 'AWSBedrockEmbeddings')
},
async listRegions(): Promise<INodeOptionsValue[]> {
return await getRegions(MODEL_TYPE.EMBEDDING, 'AWSBedrockEmbeddings')
}
}
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
const iRegion = nodeData.inputs?.region as string
const iModel = nodeData.inputs?.model as string
const customModel = nodeData.inputs?.customModel as string
const obj: BedrockEmbeddingsParams = {
model: customModel ? customModel : iModel,
region: iRegion
}
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
if (credentialData && Object.keys(credentialData).length !== 0) {
const credentialApiKey = getCredentialParam('awsKey', credentialData, nodeData)
const credentialApiSecret = getCredentialParam('awsSecret', credentialData, nodeData)
const credentialApiSession = getCredentialParam('awsSession', credentialData, nodeData)
obj.credentials = {
accessKeyId: credentialApiKey,
secretAccessKey: credentialApiSecret,
sessionToken: credentialApiSession
}
}
const client = new BedrockRuntimeClient({
region: obj.region,
credentials: obj.credentials
})
const model = new BedrockEmbeddings(obj)
// Avoid Illegal Invocation
model.embedQuery = async (document: string): Promise<number[]> => {
return await embedText(document, client, iModel)
}
model.embedDocuments = async (documents: string[]): Promise<number[][]> => {
return Promise.all(documents.map((document) => embedText(document, client, iModel)))
}
return model
}
}
const embedText = async (text: string, client: BedrockRuntimeClient, model: string): Promise<number[]> => {
// replace newlines, which can negatively affect performance.
const cleanedText = text.replace(/\n/g, ' ')
const res = await client.send(
new InvokeModelCommand({
modelId: model,
body: JSON.stringify({
inputText: cleanedText
}),
contentType: 'application/json',
accept: 'application/json'
})
)
try {
const body = new TextDecoder().decode(res.body)
return JSON.parse(body).embedding
} catch (e) {
throw new Error('An invalid response was returned by Bedrock.')
}
}
module.exports = { nodeClass: AWSBedrockEmbedding_Embeddings }