Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/components/credentials/LMStudioApi.credential.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { INodeCredential, INodeParams } from '../src/Interface'

class LMStudioApi implements INodeCredential {
label: string
name: string
version: number
inputs: INodeParams[]

constructor() {
this.label = 'LM Studio API'
this.name = 'lmStudioApi'
this.version = 1.0
this.inputs = [
{
label: 'LM Studio API Key',
name: 'lmStudioApiKey',
type: 'password'
}
]
}
}

module.exports = { credClass: LMStudioApi }
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { ClientOptions, OpenAIEmbeddings, OpenAIEmbeddingsParams } from '@langchain/openai'
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'

class LMStudioEmbedding_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 = 'LM Studio Embeddings'
this.name = 'lmStudioEmbeddings'
this.version = 1.0
this.type = 'LMStudioEmbeddings'
this.icon = 'lmstudio.svg'
this.category = 'Embeddings'
this.description = "Generate embeddings using LM Studio's OpenAI-compatible API"
this.baseClasses = [this.type, ...getBaseClasses(OpenAIEmbeddings)]
this.credential = {
label: 'Connect Credential',
name: 'credential',
type: 'credential',
credentialNames: ['lmStudioApi'],
optional: true
}
this.inputs = [
{
label: 'Base URL',
name: 'baseUrl',
type: 'string',
default: 'http://localhost:1234/v1'
},
{
label: 'Model Name',
name: 'modelName',
type: 'string',
default: 'text-embedding-nomic-embed-text-v1.5'
},
{
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: 'Dimensions',
name: 'dimensions',
type: 'number',
optional: true,
additionalParams: true
}
]
}

async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
const baseUrl = nodeData.inputs?.baseUrl as string
const modelName = nodeData.inputs?.modelName as string
const stripNewLines = nodeData.inputs?.stripNewLines as boolean
const batchSize = nodeData.inputs?.batchSize as string
const timeout = nodeData.inputs?.timeout as string
const dimensions = nodeData.inputs?.dimensions as string

if (nodeData.inputs?.credentialId) {
nodeData.credential = nodeData.inputs?.credentialId
}

const credentialData = await getCredentialData(nodeData.credential ?? '', options)
const lmStudioApiKey = getCredentialParam('lmStudioApiKey', credentialData, nodeData)

const obj: Partial<OpenAIEmbeddingsParams> & { openAIApiKey?: string; configuration?: ClientOptions } = {
modelName,
openAIApiKey: 'sk-'
}

if (lmStudioApiKey) obj.openAIApiKey = lmStudioApiKey
if (stripNewLines !== undefined) obj.stripNewLines = stripNewLines
if (batchSize) obj.batchSize = parseInt(batchSize, 10)
if (timeout) obj.timeout = parseInt(timeout, 10)
if (dimensions) obj.dimensions = parseInt(dimensions, 10)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for handling numeric inputs (along with their declarations on lines 81-83) can be made more robust. The if (variable) check evaluates to false for a numeric value of 0, which might be a valid input for timeout. Also, the as string type assertion is unsafe, and parseInt can result in NaN for invalid inputs.

Consider this more robust approach that validates the input before parsing and assigning it. This also makes the separate variable declarations on lines 81-83 unnecessary. This suggestion aligns with the repository's guideline to use loose equality (== null) for nullish checks in TypeScript, covering both null and undefined.

Suggested change
if (batchSize) obj.batchSize = parseInt(batchSize, 10)
if (timeout) obj.timeout = parseInt(timeout, 10)
if (dimensions) obj.dimensions = parseInt(dimensions, 10)
if (nodeData.inputs?.batchSize != null && nodeData.inputs?.batchSize !== '') {
const batchSize = parseInt(String(nodeData.inputs.batchSize), 10)
if (!isNaN(batchSize)) obj.batchSize = batchSize
}
if (nodeData.inputs?.timeout != null && nodeData.inputs?.timeout !== '') {
const timeout = parseInt(String(nodeData.inputs.timeout), 10)
if (!isNaN(timeout)) obj.timeout = timeout
}
if (nodeData.inputs?.dimensions != null && nodeData.inputs?.dimensions !== '') {
const dimensions = parseInt(String(nodeData.inputs.dimensions), 10)
if (!isNaN(dimensions)) obj.dimensions = dimensions
}
References
  1. In JavaScript/TypeScript, use loose equality (== null) as a standard idiom for a 'nullish' check that covers both null and undefined.


if (baseUrl) {
obj.configuration = {
baseURL: baseUrl
}
}

const model = new OpenAIEmbeddings(obj)
return model
}
}

module.exports = { nodeClass: LMStudioEmbedding_Embeddings }
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.