{"version":3,"file":"memory.cjs","names":["VectorStore","cosine","Document"],"sources":["../../src/vectorstores/memory.ts"],"sourcesContent":["import {\n  MaxMarginalRelevanceSearchOptions,\n  VectorStore,\n} from \"@langchain/core/vectorstores\";\nimport type { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport { Document, DocumentInterface } from \"@langchain/core/documents\";\nimport { maximalMarginalRelevance } from \"@langchain/core/utils/math\";\nimport { cosine } from \"../util/ml-distance/similarities.js\";\n\n/**\n * Interface representing a vector in memory. It includes the content\n * (text), the corresponding embedding (vector), and any associated\n * metadata.\n */\ninterface MemoryVector {\n  content: string;\n  embedding: number[];\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  metadata: Record<string, any>;\n  id?: string;\n}\n\n/**\n * Interface for the arguments that can be passed to the\n * `MemoryVectorStore` constructor. It includes an optional `similarity`\n * function.\n */\nexport interface MemoryVectorStoreArgs {\n  similarity?: typeof cosine;\n}\n\n/**\n * In-memory, ephemeral vector store.\n *\n * Setup:\n * Install `langchain`:\n *\n * ```bash\n * npm install langchain\n * ```\n *\n * ## [Constructor args](https://api.js.langchain.com/classes/langchain.vectorstores_memory.MemoryVectorStore.html#constructor)\n *\n * <details open>\n * <summary><strong>Instantiate</strong></summary>\n *\n * ```typescript\n * import { MemoryVectorStore } from 'langchain/vectorstores/memory';\n * // Or other embeddings\n * import { OpenAIEmbeddings } from '@langchain/openai';\n *\n * const embeddings = new OpenAIEmbeddings({\n *   model: \"text-embedding-3-small\",\n * });\n *\n * const vectorStore = new MemoryVectorStore(embeddings);\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Add documents</strong></summary>\n *\n * ```typescript\n * import type { Document } from '@langchain/core/documents';\n *\n * const document1 = { pageContent: \"foo\", metadata: { baz: \"bar\" } };\n * const document2 = { pageContent: \"thud\", metadata: { bar: \"baz\" } };\n * const document3 = { pageContent: \"i will be deleted :(\", metadata: {} };\n *\n * const documents: Document[] = [document1, document2, document3];\n *\n * await vectorStore.addDocuments(documents);\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Similarity search</strong></summary>\n *\n * ```typescript\n * const results = await vectorStore.similaritySearch(\"thud\", 1);\n * for (const doc of results) {\n *   console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * thud [{\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n *\n * <details>\n * <summary><strong>Similarity search with filter</strong></summary>\n *\n * ```typescript\n * const resultsWithFilter = await vectorStore.similaritySearch(\"thud\", 1, { baz: \"bar\" });\n *\n * for (const doc of resultsWithFilter) {\n *   console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * foo [{\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n *\n * <details>\n * <summary><strong>Similarity search with score</strong></summary>\n *\n * ```typescript\n * const resultsWithScore = await vectorStore.similaritySearchWithScore(\"qux\", 1);\n * for (const [doc, score] of resultsWithScore) {\n *   console.log(`* [SIM=${score.toFixed(6)}] ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);\n * }\n * // Output: * [SIM=0.000000] qux [{\"bar\":\"baz\",\"baz\":\"bar\"}]\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>As a retriever</strong></summary>\n *\n * ```typescript\n * const retriever = vectorStore.asRetriever({\n *   searchType: \"mmr\", // Leave blank for standard similarity search\n *   k: 1,\n * });\n * const resultAsRetriever = await retriever.invoke(\"thud\");\n * console.log(resultAsRetriever);\n *\n * // Output: [Document({ metadata: { \"baz\":\"bar\" }, pageContent: \"thud\" })]\n * ```\n * </details>\n *\n * <br />\n */\nexport class MemoryVectorStore extends VectorStore {\n  declare FilterType: (doc: Document) => boolean;\n\n  memoryVectors: MemoryVector[] = [];\n\n  similarity: typeof cosine;\n\n  _vectorstoreType(): string {\n    return \"memory\";\n  }\n\n  constructor(\n    embeddings: EmbeddingsInterface,\n    { similarity, ...rest }: MemoryVectorStoreArgs = {}\n  ) {\n    super(embeddings, rest);\n\n    this.similarity = similarity ?? cosine;\n  }\n\n  /**\n   * Method to add documents to the memory vector store. It extracts the\n   * text from each document, generates embeddings for them, and adds the\n   * resulting vectors to the store.\n   * @param documents Array of `Document` instances to be added to the store.\n   * @returns Promise that resolves when all documents have been added.\n   */\n  async addDocuments(documents: Document[]): Promise<void> {\n    const texts = documents.map(({ pageContent }) => pageContent);\n    return this.addVectors(\n      await this.embeddings.embedDocuments(texts),\n      documents\n    );\n  }\n\n  /**\n   * Method to add vectors to the memory vector store. It creates\n   * `MemoryVector` instances for each vector and document pair and adds\n   * them to the store.\n   * @param vectors Array of vectors to be added to the store.\n   * @param documents Array of `Document` instances corresponding to the vectors.\n   * @returns Promise that resolves when all vectors have been added.\n   */\n  async addVectors(vectors: number[][], documents: Document[]): Promise<void> {\n    const memoryVectors = vectors.map((embedding, idx) => ({\n      content: documents[idx].pageContent,\n      embedding,\n      metadata: documents[idx].metadata,\n      id: documents[idx].id,\n    }));\n\n    this.memoryVectors = this.memoryVectors.concat(memoryVectors);\n  }\n\n  protected async _queryVectors(\n    query: number[],\n    k: number,\n    filter?: this[\"FilterType\"]\n  ) {\n    const filterFunction = (memoryVector: MemoryVector) => {\n      if (!filter) {\n        return true;\n      }\n\n      const doc = new Document({\n        metadata: memoryVector.metadata,\n        pageContent: memoryVector.content,\n        id: memoryVector.id,\n      });\n      return filter(doc);\n    };\n    const filteredMemoryVectors = this.memoryVectors.filter(filterFunction);\n    return filteredMemoryVectors\n      .map((vector, index) => ({\n        similarity: this.similarity(query, vector.embedding),\n        index,\n        metadata: vector.metadata,\n        content: vector.content,\n        embedding: vector.embedding,\n        id: vector.id,\n      }))\n      .sort((a, b) => (a.similarity > b.similarity ? -1 : 0))\n      .slice(0, k);\n  }\n\n  /**\n   * Method to perform a similarity search in the memory vector store. It\n   * calculates the similarity between the query vector and each vector in\n   * the store, sorts the results by similarity, and returns the top `k`\n   * results along with their scores.\n   * @param query Query vector to compare against the vectors in the store.\n   * @param k Number of top results to return.\n   * @param filter Optional filter function to apply to the vectors before performing the search.\n   * @returns Promise that resolves with an array of tuples, each containing a `Document` and its similarity score.\n   */\n  async similaritySearchVectorWithScore(\n    query: number[],\n    k: number,\n    filter?: this[\"FilterType\"]\n  ): Promise<[Document, number][]> {\n    const searches = await this._queryVectors(query, k, filter);\n    const result: [Document, number][] = searches.map((search) => [\n      new Document({\n        metadata: search.metadata,\n        pageContent: search.content,\n        id: search.id,\n      }),\n      search.similarity,\n    ]);\n\n    return result;\n  }\n\n  async maxMarginalRelevanceSearch(\n    query: string,\n    options: MaxMarginalRelevanceSearchOptions<this[\"FilterType\"]>\n  ): Promise<DocumentInterface[]> {\n    const queryEmbedding = await this.embeddings.embedQuery(query);\n\n    const searches = await this._queryVectors(\n      queryEmbedding,\n      options.fetchK ?? 20,\n      options.filter\n    );\n\n    const embeddingList = searches.map((searchResp) => searchResp.embedding);\n\n    const mmrIndexes = maximalMarginalRelevance(\n      queryEmbedding,\n      embeddingList,\n      options.lambda,\n      options.k\n    );\n\n    return mmrIndexes.map(\n      (idx) =>\n        new Document({\n          metadata: searches[idx].metadata,\n          pageContent: searches[idx].content,\n          id: searches[idx].id,\n        })\n    );\n  }\n\n  /**\n   * Static method to create a `MemoryVectorStore` instance from an array of\n   * texts. It creates a `Document` for each text and metadata pair, and\n   * adds them to the store.\n   * @param texts Array of texts to be added to the store.\n   * @param metadatas Array or single object of metadata corresponding to the texts.\n   * @param embeddings `Embeddings` instance used to generate embeddings for the texts.\n   * @param dbConfig Optional `MemoryVectorStoreArgs` to configure the `MemoryVectorStore` instance.\n   * @returns Promise that resolves with a new `MemoryVectorStore` instance.\n   */\n  static async fromTexts(\n    texts: string[],\n    metadatas: object[] | object,\n    embeddings: EmbeddingsInterface,\n    dbConfig?: MemoryVectorStoreArgs\n  ): Promise<MemoryVectorStore> {\n    const docs: Document[] = [];\n    for (let i = 0; i < texts.length; i += 1) {\n      const metadata = Array.isArray(metadatas) ? metadatas[i] : metadatas;\n      const newDoc = new Document({\n        pageContent: texts[i],\n        metadata,\n      });\n      docs.push(newDoc);\n    }\n    return MemoryVectorStore.fromDocuments(docs, embeddings, dbConfig);\n  }\n\n  /**\n   * Static method to create a `MemoryVectorStore` instance from an array of\n   * `Document` instances. It adds the documents to the store.\n   * @param docs Array of `Document` instances to be added to the store.\n   * @param embeddings `Embeddings` instance used to generate embeddings for the documents.\n   * @param dbConfig Optional `MemoryVectorStoreArgs` to configure the `MemoryVectorStore` instance.\n   * @returns Promise that resolves with a new `MemoryVectorStore` instance.\n   */\n  static async fromDocuments(\n    docs: Document[],\n    embeddings: EmbeddingsInterface,\n    dbConfig?: MemoryVectorStoreArgs\n  ): Promise<MemoryVectorStore> {\n    const instance = new this(embeddings, dbConfig);\n    await instance.addDocuments(docs);\n    return instance;\n  }\n\n  /**\n   * Static method to create a `MemoryVectorStore` instance from an existing\n   * index. It creates a new `MemoryVectorStore` instance without adding any\n   * documents or vectors.\n   * @param embeddings `Embeddings` instance used to generate embeddings for the documents.\n   * @param dbConfig Optional `MemoryVectorStoreArgs` to configure the `MemoryVectorStore` instance.\n   * @returns Promise that resolves with a new `MemoryVectorStore` instance.\n   */\n  static async fromExistingIndex(\n    embeddings: EmbeddingsInterface,\n    dbConfig?: MemoryVectorStoreArgs\n  ): Promise<MemoryVectorStore> {\n    const instance = new this(embeddings, dbConfig);\n    return instance;\n  }\n}\n"],"mappings":"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"}