{"version":3,"file":"upstash.cjs","names":["VectorStore","FakeEmbeddings","AsyncCaller","Document"],"sources":["../../src/vectorstores/upstash.ts"],"sourcesContent":["import * as uuid from \"uuid\";\nimport { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport { VectorStore } from \"@langchain/core/vectorstores\";\nimport { Index as UpstashIndex, type QueryResult } from \"@upstash/vector\";\nimport { Document, DocumentInterface } from \"@langchain/core/documents\";\nimport { chunkArray } from \"@langchain/core/utils/chunk_array\";\nimport { FakeEmbeddings } from \"@langchain/core/utils/testing\";\n\nimport {\n  AsyncCaller,\n  AsyncCallerParams,\n} from \"@langchain/core/utils/async_caller\";\n\n/**\n * This interface defines the arguments for the UpstashVectorStore class.\n */\nexport interface UpstashVectorLibArgs extends AsyncCallerParams {\n  index: UpstashIndex;\n  filter?: string;\n  namespace?: string;\n}\n\n// oxlint-disable-next-line typescript/no-explicit-any\nexport type UpstashMetadata = Record<string, any>;\n\nexport type UpstashQueryMetadata = UpstashMetadata & {\n  // oxlint-disable-next-line typescript/no-explicit-any\n  _pageContentLC: any;\n};\n\n/**\n * Type that defines the parameters for the delete method.\n * It can either contain the target id(s) or the deleteAll config to reset all the vectors.\n */\nexport type UpstashDeleteParams =\n  | {\n      ids: string | string[];\n      deleteAll?: never;\n    }\n  | { deleteAll: boolean; ids?: never };\n\nconst CONCURRENT_UPSERT_LIMIT = 1000;\n\n/**\n * The main class that extends the 'VectorStore' class. It provides\n * methods for interacting with Upstash index, such as adding documents,\n * deleting documents, performing similarity search and more.\n */\nexport class UpstashVectorStore extends VectorStore {\n  declare FilterType: string;\n\n  index: UpstashIndex;\n\n  caller: AsyncCaller;\n\n  useUpstashEmbeddings?: boolean;\n\n  filter?: this[\"FilterType\"];\n\n  namespace?: string;\n\n  _vectorstoreType(): string {\n    return \"upstash\";\n  }\n\n  constructor(embeddings: EmbeddingsInterface, args: UpstashVectorLibArgs) {\n    super(embeddings, args);\n    // Special case where the embeddings instance is a FakeEmbeddings instance. In this case, we need to disable \"instanceof\" rule.\n    // eslint-disable-next-line no-instanceof/no-instanceof\n    if (embeddings instanceof FakeEmbeddings) {\n      this.useUpstashEmbeddings = true;\n    }\n\n    const { index, namespace, ...asyncCallerArgs } = args;\n\n    this.index = index;\n    this.caller = new AsyncCaller(asyncCallerArgs);\n    this.filter = args.filter;\n    this.namespace = namespace;\n  }\n\n  /**\n   * This method adds documents to Upstash database. Documents are first converted to vectors\n   * using the provided embeddings instance, and then upserted to the database.\n   * @param documents Array of Document objects to be added to the database.\n   * @param options Optional object containing array of ids for the documents.\n   * @returns Promise that resolves with the ids of the provided documents when the upsert operation is done.\n   */\n  async addDocuments(\n    documents: DocumentInterface[],\n    options?: { ids?: string[]; useUpstashEmbeddings?: boolean }\n  ) {\n    const texts = documents.map(({ pageContent }) => pageContent);\n\n    if (this.useUpstashEmbeddings || options?.useUpstashEmbeddings) {\n      return this._addData(documents, options);\n    }\n\n    const embeddings = await this.embeddings.embedDocuments(texts);\n\n    return this.addVectors(embeddings, documents, options);\n  }\n\n  /**\n   * This method adds the provided vectors to Upstash database.\n   * @param vectors  Array of vectors to be added to the Upstash database.\n   * @param documents Array of Document objects, each associated with a vector.\n   * @param options Optional object containing the array of ids foor the vectors.\n   * @returns Promise that resolves with the ids of the provided documents when the upsert operation is done.\n   */\n  async addVectors(\n    vectors: number[][],\n    documents: DocumentInterface[],\n    options?: { ids?: string[] }\n  ) {\n    const documentIds =\n      options?.ids ?? Array.from({ length: vectors.length }, () => uuid.v4());\n\n    const upstashVectors = vectors.map((vector, index) => {\n      const metadata = {\n        _pageContentLC: documents[index].pageContent,\n        ...documents[index].metadata,\n      };\n\n      const id = documentIds[index];\n\n      return {\n        id,\n        vector,\n        metadata,\n      };\n    });\n\n    const namespace = this.index.namespace(this.namespace ?? \"\");\n\n    const vectorChunks = chunkArray(upstashVectors, CONCURRENT_UPSERT_LIMIT);\n\n    const batchRequests = vectorChunks.map((chunk) =>\n      this.caller.call(async () => namespace.upsert(chunk))\n    );\n\n    await Promise.all(batchRequests);\n\n    return documentIds;\n  }\n\n  /**\n   * This method adds the provided documents to Upstash database. The pageContent of the documents will be embedded by Upstash Embeddings.\n   * @param documents Array of Document objects to be added to the Upstash database.\n   * @param options Optional object containing the array of ids for the documents.\n   * @returns Promise that resolves with the ids of the provided documents when the upsert operation is done.\n   */\n  protected async _addData(\n    documents: DocumentInterface[],\n    options?: { ids?: string[] }\n  ) {\n    const documentIds =\n      options?.ids ?? Array.from({ length: documents.length }, () => uuid.v4());\n\n    const upstashVectorsWithData = documents.map((document, index) => {\n      const metadata = {\n        _pageContentLC: documents[index].pageContent,\n        ...documents[index].metadata,\n      };\n\n      const id = documentIds[index];\n\n      return {\n        id,\n        data: document.pageContent,\n        metadata,\n      };\n    });\n\n    const namespace = this.index.namespace(this.namespace ?? \"\");\n    const vectorChunks = chunkArray(\n      upstashVectorsWithData,\n      CONCURRENT_UPSERT_LIMIT\n    );\n\n    const batchRequests = vectorChunks.map((chunk) =>\n      this.caller.call(async () => namespace.upsert(chunk))\n    );\n\n    await Promise.all(batchRequests);\n\n    return documentIds;\n  }\n\n  /**\n   * This method deletes documents from the Upstash database. You can either\n   * provide the target ids, or delete all vectors in the database.\n   * @param params Object containing either array of ids of the documents or boolean deleteAll.\n   * @returns Promise that resolves when the specified documents have been deleted from the database.\n   */\n  async delete(params: UpstashDeleteParams): Promise<void> {\n    const namespace = this.index.namespace(this.namespace ?? \"\");\n    if (params.deleteAll) {\n      await namespace.reset();\n    } else if (params.ids) {\n      await namespace.delete(params.ids);\n    }\n  }\n\n  protected async _runUpstashQuery(\n    query: number[] | string,\n    k: number,\n    filter?: this[\"FilterType\"],\n    options?: { includeVectors: boolean }\n  ) {\n    let queryResult: QueryResult<UpstashQueryMetadata>[] = [];\n\n    const namespace = this.index.namespace(this.namespace ?? \"\");\n\n    if (typeof query === \"string\") {\n      queryResult = await namespace.query<UpstashQueryMetadata>({\n        data: query,\n        topK: k,\n        includeMetadata: true,\n        filter,\n        ...options,\n      });\n    } else {\n      queryResult = await namespace.query<UpstashQueryMetadata>({\n        vector: query,\n        topK: k,\n        includeMetadata: true,\n        filter,\n        ...options,\n      });\n    }\n\n    return queryResult;\n  }\n\n  /**\n   * This method performs a similarity search in the Upstash database\n   * over the existing vectors.\n   * @param query Query vector for the similarity search.\n   * @param k The number of similar vectors to return as result.\n   * @returns Promise that resolves with an array of tuples, each containing\n   *  Document object and similarity score. The length of the result will be\n   *  maximum of 'k' and vectors in the index.\n   */\n  async similaritySearchVectorWithScore(\n    query: number[] | string,\n    k: number,\n    filter?: this[\"FilterType\"]\n  ): Promise<[DocumentInterface, number][]> {\n    const results = await this._runUpstashQuery(query, k, filter);\n\n    const searchResult: [DocumentInterface, number][] = results.map((res) => {\n      const { _pageContentLC, ...metadata } = (res.metadata ??\n        {}) as UpstashQueryMetadata;\n      return [\n        new Document({\n          metadata,\n          pageContent: _pageContentLC,\n        }),\n        res.score,\n      ];\n    });\n\n    return searchResult;\n  }\n\n  /**\n   * This method creates a new UpstashVector instance from an array of texts.\n   * The texts are initially converted to Document instances and added to Upstash\n   * database.\n   * @param texts The texts to create the documents from.\n   * @param metadatas The metadata values associated with the texts.\n   * @param embeddings Embedding interface of choice, to create the text embeddings.\n   * @param dbConfig Object containing the Upstash database configs.\n   * @returns Promise that resolves with a new UpstashVector instance.\n   */\n  static async fromTexts(\n    texts: string[],\n    metadatas: UpstashMetadata | UpstashMetadata[],\n    embeddings: EmbeddingsInterface,\n    dbConfig: UpstashVectorLibArgs\n  ): Promise<UpstashVectorStore> {\n    const docs: DocumentInterface[] = [];\n\n    for (let i = 0; i < texts.length; i += 1) {\n      const metadata = Array.isArray(metadatas) ? metadatas[i] : metadatas;\n      const newDocument = new Document({\n        pageContent: texts[i],\n        metadata,\n      });\n      docs.push(newDocument);\n    }\n\n    return this.fromDocuments(docs, embeddings, dbConfig);\n  }\n\n  /**\n   * This method creates a new UpstashVector instance from an array of Document instances.\n   * @param docs The docs to be added to Upstash database.\n   * @param embeddings Embedding interface of choice, to create the embeddings.\n   * @param dbConfig Object containing the Upstash database configs.\n   * @returns Promise that resolves with a new UpstashVector instance\n   */\n  static async fromDocuments(\n    docs: DocumentInterface[],\n    embeddings: EmbeddingsInterface,\n    dbConfig: UpstashVectorLibArgs\n  ): Promise<UpstashVectorStore> {\n    const instance = new this(embeddings, dbConfig);\n    await instance.addDocuments(docs);\n    return instance;\n  }\n\n  /**\n   * This method creates a new UpstashVector instance from an existing index.\n   * @param embeddings Embedding interface of the choice, to create the embeddings.\n   * @param dbConfig Object containing the Upstash database configs.\n   * @returns\n   */\n  static async fromExistingIndex(\n    embeddings: EmbeddingsInterface,\n    dbConfig: UpstashVectorLibArgs\n  ): Promise<UpstashVectorStore> {\n    const instance = new this(embeddings, dbConfig);\n    return instance;\n  }\n}\n"],"mappings":"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"}