Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
import { FaissStore } from 'langchain/vectorstores/faiss'
import { Embeddings } from 'langchain/embeddings/base'
import { getBaseClasses } from '../../../src/utils'

class Faiss_Existing_VectorStores implements INode {
label: string
name: string
description: string
type: string
icon: string
category: string
baseClasses: string[]
inputs: INodeParams[]
outputs: INodeOutputsValue[]

constructor() {
this.label = 'Faiss Load Existing Index'
this.name = 'faissExistingIndex'
this.type = 'Faiss'
this.icon = 'faiss.svg'
this.category = 'Vector Stores'
this.description = 'Load existing index from Faiss (i.e: Document has been upserted)'
this.baseClasses = [this.type, 'VectorStoreRetriever', 'BaseRetriever']
this.inputs = [
{
label: 'Embeddings',
name: 'embeddings',
type: 'Embeddings'
},
{
label: 'Base Path to load',
name: 'basePath',
description: 'Path to load faiss.index file',
placeholder: `C:\\Users\\User\\Desktop`,
type: 'string'
}
]
this.outputs = [
{
label: 'Faiss Retriever',
name: 'retriever',
baseClasses: this.baseClasses
},
{
label: 'Faiss Vector Store',
name: 'vectorStore',
baseClasses: [this.type, ...getBaseClasses(FaissStore)]
}
]
}

async init(nodeData: INodeData): Promise<any> {
const embeddings = nodeData.inputs?.embeddings as Embeddings
const basePath = nodeData.inputs?.basePath as string
const output = nodeData.outputs?.output as string

const vectorStore = await FaissStore.load(basePath, embeddings)

if (output === 'retriever') {
const retriever = vectorStore.asRetriever()
return retriever
} else if (output === 'vectorStore') {
return vectorStore
}
return vectorStore
}
}

module.exports = { nodeClass: Faiss_Existing_VectorStores }
10 changes: 10 additions & 0 deletions packages/components/nodes/vectorstores/Faiss_Existing/faiss.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
import { Embeddings } from 'langchain/embeddings/base'
import { Document } from 'langchain/document'
import { getBaseClasses } from '../../../src/utils'
import { FaissStore } from 'langchain/vectorstores/faiss'

class FaissUpsert_VectorStores implements INode {
label: string
name: string
description: string
type: string
icon: string
category: string
baseClasses: string[]
inputs: INodeParams[]
outputs: INodeOutputsValue[]

constructor() {
this.label = 'Faiss Upsert Document'
this.name = 'faissUpsert'
this.type = 'Faiss'
this.icon = 'faiss.svg'
this.category = 'Vector Stores'
this.description = 'Upsert documents to Faiss'
this.baseClasses = [this.type, 'VectorStoreRetriever', 'BaseRetriever']
this.inputs = [
{
label: 'Document',
name: 'document',
type: 'Document',
list: true
},
{
label: 'Embeddings',
name: 'embeddings',
type: 'Embeddings'
},
{
label: 'Base Path to store',
name: 'basePath',
description: 'Path to store faiss.index file',
placeholder: `C:\\Users\\User\\Desktop`,
type: 'string'
}
]
this.outputs = [
{
label: 'Faiss Retriever',
name: 'retriever',
baseClasses: this.baseClasses
},
{
label: 'Faiss Vector Store',
name: 'vectorStore',
baseClasses: [this.type, ...getBaseClasses(FaissStore)]
}
]
}

async init(nodeData: INodeData): Promise<any> {
const docs = nodeData.inputs?.document as Document[]
const embeddings = nodeData.inputs?.embeddings as Embeddings
const output = nodeData.outputs?.output as string
const basePath = nodeData.inputs?.basePath as string

const flattenDocs = docs && docs.length ? docs.flat() : []
const finalDocs = []
for (let i = 0; i < flattenDocs.length; i += 1) {
finalDocs.push(new Document(flattenDocs[i]))
}

const vectorStore = await FaissStore.fromDocuments(finalDocs, embeddings)
await vectorStore.save(basePath)

if (output === 'retriever') {
const retriever = vectorStore.asRetriever()
return retriever
} else if (output === 'vectorStore') {
return vectorStore
}
return vectorStore
}
}

module.exports = { nodeClass: FaissUpsert_VectorStores }
10 changes: 10 additions & 0 deletions packages/components/nodes/vectorstores/Faiss_Upsert/faiss.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"d3-dsv": "2",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"faiss-node": "^0.2.1",
"form-data": "^4.0.0",
"graphql": "^16.6.0",
"langchain": "^0.0.84",
Expand Down
4 changes: 3 additions & 1 deletion packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import {
findAvailableConfigs,
isSameOverrideConfig,
replaceAllAPIKeys,
isFlowValidForStream
isFlowValidForStream,
isVectorStoreFaiss
} from './utils'
import { cloneDeep } from 'lodash'
import { getDataSource } from './DataSource'
Expand Down Expand Up @@ -634,6 +635,7 @@ export class App {
const nodeModule = await import(nodeInstanceFilePath)
const nodeInstance = new nodeModule.nodeClass()

isStreamValid = isStreamValid && !isVectorStoreFaiss(nodeToExecuteData)
const result = isStreamValid
? await nodeInstance.run(nodeToExecuteData, incomingInput.question, {
chatHistory: incomingInput.history,
Expand Down
30 changes: 27 additions & 3 deletions packages/server/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
INodeData,
IOverrideConfig
} from '../Interface'
import { cloneDeep, get } from 'lodash'
import { cloneDeep, get, omit, merge } from 'lodash'
import { ICommonObject, getInputVariables } from 'flowise-components'
import { scryptSync, randomBytes, timingSafeEqual } from 'crypto'

Expand Down Expand Up @@ -317,6 +317,25 @@ export const getVariableValue = (paramValue: string, reactFlowNodes: IReactFlowN
return returnVal
}

/**
* Temporarily disable streaming if vectorStore is Faiss
* @param {INodeData} flowNodeData
* @returns {boolean}
*/
export const isVectorStoreFaiss = (flowNodeData: INodeData) => {
if (flowNodeData.inputs && flowNodeData.inputs.vectorStoreRetriever) {
const vectorStoreRetriever = flowNodeData.inputs.vectorStoreRetriever
if (typeof vectorStoreRetriever === 'string' && vectorStoreRetriever.includes('faiss')) return true
if (
typeof vectorStoreRetriever === 'object' &&
vectorStoreRetriever.vectorStore &&
vectorStoreRetriever.vectorStore.constructor.name === 'FaissStore'
)
return true
}
return false
}

/**
* Loop through each inputs and resolve variable if neccessary
* @param {INodeData} reactFlowNodeData
Expand All @@ -325,7 +344,12 @@ export const getVariableValue = (paramValue: string, reactFlowNodes: IReactFlowN
* @returns {INodeData}
*/
export const resolveVariables = (reactFlowNodeData: INodeData, reactFlowNodes: IReactFlowNode[], question: string): INodeData => {
const flowNodeData = cloneDeep(reactFlowNodeData)
let flowNodeData = cloneDeep(reactFlowNodeData)
if (reactFlowNodeData.instance && isVectorStoreFaiss(reactFlowNodeData)) {
// omit and merge because cloneDeep of instance gives "Illegal invocation" Exception
const flowNodeDataWithoutInstance = cloneDeep(omit(reactFlowNodeData, ['instance']))
flowNodeData = merge(flowNodeDataWithoutInstance, { instance: reactFlowNodeData.instance })
}
const types = 'inputs'

const getParamValues = (paramsObj: ICommonObject) => {
Expand Down Expand Up @@ -633,5 +657,5 @@ export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNod
}
}

return isChatOrLLMsExist && endingNodeData.category === 'Chains'
return isChatOrLLMsExist && endingNodeData.category === 'Chains' && !isVectorStoreFaiss(endingNodeData)
}