{"version":3,"file":"opensearch.cjs","names":["VectorStore","embeddings: EmbeddingsInterface","args: OpenSearchClientArgs","documents: Document[]","vectors: number[][]","options?: { ids?: string[] }","document: Record<string, any>","query: number[]","k: number","filter?: OpenSearchFilter | undefined","search: RequestParams.Search","hit: any","Document","texts: string[]","metadatas: object[] | object","docs: Document[]","dbConfig: OpenSearchClientArgs","dimension: number","filter: OpenSearchFilter | undefined","err: unknown","errors"],"sources":["../../src/vectorstores/opensearch.ts"],"sourcesContent":["import { Client, RequestParams, errors } from \"@opensearch-project/opensearch\";\nimport * as uuid from \"uuid\";\nimport type { EmbeddingsInterface } from \"@langchain/core/embeddings\";\nimport { VectorStore } from \"@langchain/core/vectorstores\";\nimport { Document } from \"@langchain/core/documents\";\n\ntype OpenSearchEngine = \"nmslib\" | \"hnsw\";\ntype OpenSearchSpaceType = \"l2\" | \"cosinesimil\" | \"ip\";\n\n/**\n * Interface defining the options for vector search in OpenSearch. It\n * includes the engine type, space type, and parameters for the HNSW\n * algorithm.\n */\ninterface VectorSearchOptions {\n  readonly engine?: OpenSearchEngine;\n  readonly spaceType?: OpenSearchSpaceType;\n  readonly m?: number;\n  readonly efConstruction?: number;\n  readonly efSearch?: number;\n  readonly numberOfShards?: number;\n  readonly numberOfReplicas?: number;\n}\n\n/**\n * Interface defining the arguments required to create an instance of the\n * OpenSearchVectorStore class. It includes the OpenSearch client, index\n * name, and vector search options.\n */\nexport interface OpenSearchClientArgs {\n  readonly client: Client;\n  readonly vectorFieldName?: string;\n  readonly textFieldName?: string;\n  readonly metadataFieldName?: string;\n  readonly service?: \"es\" | \"aoss\";\n  readonly indexName?: string;\n\n  readonly vectorSearchOptions?: VectorSearchOptions;\n}\n\n/**\n * Type alias for an object. It's used to define filters for OpenSearch\n * queries.\n */\ntype OpenSearchFilter = {\n  [key: string]: FilterTypeValue | (string | number)[] | string | number;\n};\n\n/**\n * FilterTypeValue for OpenSearch queries.\n */\ninterface FilterTypeValue {\n  exists?: boolean;\n  fuzzy?: string;\n  ids?: string[];\n  prefix?: string;\n  gte?: number;\n  gt?: number;\n  lte?: number;\n  lt?: number;\n  regexp?: string;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  terms_set?: Record<string, any>;\n  wildcard?: string;\n}\n\n/**\n * Class that provides a wrapper around the OpenSearch service for vector\n * search. It provides methods for adding documents and vectors to the\n * OpenSearch index, searching for similar vectors, and managing the\n * OpenSearch index.\n */\nexport class OpenSearchVectorStore extends VectorStore {\n  declare FilterType: OpenSearchFilter;\n\n  private readonly client: Client;\n\n  private readonly indexName: string;\n\n  // if true, use the Amazon OpenSearch Serverless service instead of es\n  private readonly isAoss: boolean;\n\n  private readonly engine: OpenSearchEngine;\n\n  private readonly spaceType: OpenSearchSpaceType;\n\n  private readonly efConstruction: number;\n\n  private readonly efSearch: number;\n\n  private readonly numberOfShards: number;\n\n  private readonly numberOfReplicas: number;\n\n  private readonly m: number;\n\n  private readonly vectorFieldName: string;\n\n  private readonly textFieldName: string;\n\n  private readonly metadataFieldName: string;\n\n  _vectorstoreType(): string {\n    return \"opensearch\";\n  }\n\n  constructor(embeddings: EmbeddingsInterface, args: OpenSearchClientArgs) {\n    super(embeddings, args);\n\n    this.spaceType = args.vectorSearchOptions?.spaceType ?? \"l2\";\n    this.engine = args.vectorSearchOptions?.engine ?? \"nmslib\";\n    this.m = args.vectorSearchOptions?.m ?? 16;\n    this.efConstruction = args.vectorSearchOptions?.efConstruction ?? 512;\n    this.efSearch = args.vectorSearchOptions?.efSearch ?? 512;\n    this.numberOfShards = args.vectorSearchOptions?.numberOfShards ?? 5;\n    this.numberOfReplicas = args.vectorSearchOptions?.numberOfReplicas ?? 1;\n    this.vectorFieldName = args.vectorFieldName ?? \"embedding\";\n    this.textFieldName = args.textFieldName ?? \"text\";\n    this.metadataFieldName = args.metadataFieldName ?? \"metadata\";\n\n    this.client = args.client;\n    this.indexName = args.indexName ?? \"documents\";\n    this.isAoss = (args.service ?? \"es\") === \"aoss\";\n  }\n\n  /**\n   * Method to add documents to the OpenSearch index. It first converts the\n   * documents to vectors using the embeddings, then adds the vectors to the\n   * index.\n   * @param documents The documents to be added to the OpenSearch index.\n   * @returns Promise resolving to void.\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 OpenSearch index. It ensures the index\n   * exists, then adds the vectors and associated documents to the index.\n   * @param vectors The vectors to be added to the OpenSearch index.\n   * @param documents The documents associated with the vectors.\n   * @param options Optional parameter that can contain the IDs for the documents.\n   * @returns Promise resolving to void.\n   */\n  async addVectors(\n    vectors: number[][],\n    documents: Document[],\n    options?: { ids?: string[] }\n  ): Promise<void> {\n    await this.ensureIndexExists(\n      vectors[0].length,\n      this.engine,\n      this.spaceType,\n      this.efSearch,\n      this.efConstruction,\n      this.numberOfShards,\n      this.numberOfReplicas,\n      this.m\n    );\n    const documentIds =\n      options?.ids ?? Array.from({ length: vectors.length }, () => uuid.v4());\n    const operations = vectors.flatMap((embedding, idx) => {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      const document: Record<string, any> = [\n        {\n          index: {\n            _index: this.indexName,\n            _id: documentIds[idx],\n          },\n        },\n        {\n          [this.vectorFieldName]: embedding,\n          [this.textFieldName]: documents[idx].pageContent,\n          [this.metadataFieldName]: documents[idx].metadata,\n        },\n      ];\n\n      // aoss does not support document id\n      if (this.isAoss) {\n        delete document[0].index?._id;\n      }\n\n      return document;\n    });\n    await this.client.bulk({ body: operations });\n\n    // aoss does not support refresh\n    if (!this.isAoss) {\n      await this.client.indices.refresh({ index: this.indexName });\n    }\n  }\n\n  /**\n   * Method to perform a similarity search on the OpenSearch index using a\n   * query vector. It returns the k most similar documents and their scores.\n   * @param query The query vector.\n   * @param k The number of similar documents to return.\n   * @param filter Optional filter for the OpenSearch query.\n   * @returns Promise resolving to an array of tuples, each containing a Document and its score.\n   */\n  async similaritySearchVectorWithScore(\n    query: number[],\n    k: number,\n    filter?: OpenSearchFilter | undefined\n  ): Promise<[Document, number][]> {\n    const search: RequestParams.Search = {\n      index: this.indexName,\n      body: {\n        query: {\n          bool: {\n            filter: { bool: this.buildMetadataTerms(filter) },\n            must: [\n              {\n                knn: {\n                  [this.vectorFieldName]: { vector: query, k },\n                },\n              },\n            ],\n          },\n        },\n        size: k,\n      },\n    };\n\n    const { body } = await this.client.search(search);\n\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    return body.hits.hits.map((hit: any) => [\n      new Document({\n        pageContent: hit._source[this.textFieldName],\n        metadata: hit._source[this.metadataFieldName],\n        id: hit._id,\n      }),\n      hit._score,\n    ]);\n  }\n\n  /**\n   * Static method to create a new OpenSearchVectorStore from an array of\n   * texts, their metadata, embeddings, and OpenSearch client arguments.\n   * @param texts The texts to be converted into documents and added to the OpenSearch index.\n   * @param metadatas The metadata associated with the texts. Can be an array of objects or a single object.\n   * @param embeddings The embeddings used to convert the texts into vectors.\n   * @param args The OpenSearch client arguments.\n   * @returns Promise resolving to a new instance of OpenSearchVectorStore.\n   */\n  static fromTexts(\n    texts: string[],\n    metadatas: object[] | object,\n    embeddings: EmbeddingsInterface,\n    args: OpenSearchClientArgs\n  ): Promise<OpenSearchVectorStore> {\n    const documents = texts.map((text, idx) => {\n      const metadata = Array.isArray(metadatas) ? metadatas[idx] : metadatas;\n      return new Document({ pageContent: text, metadata });\n    });\n\n    return OpenSearchVectorStore.fromDocuments(documents, embeddings, args);\n  }\n\n  /**\n   * Static method to create a new OpenSearchVectorStore from an array of\n   * Documents, embeddings, and OpenSearch client arguments.\n   * @param docs The documents to be added to the OpenSearch index.\n   * @param embeddings The embeddings used to convert the documents into vectors.\n   * @param dbConfig The OpenSearch client arguments.\n   * @returns Promise resolving to a new instance of OpenSearchVectorStore.\n   */\n  static async fromDocuments(\n    docs: Document[],\n    embeddings: EmbeddingsInterface,\n    dbConfig: OpenSearchClientArgs\n  ): Promise<OpenSearchVectorStore> {\n    const store = new OpenSearchVectorStore(embeddings, dbConfig);\n    await store.addDocuments(docs).then(() => store);\n    return store;\n  }\n\n  /**\n   * Static method to create a new OpenSearchVectorStore from an existing\n   * OpenSearch index, embeddings, and OpenSearch client arguments.\n   * @param embeddings The embeddings used to convert the documents into vectors.\n   * @param dbConfig The OpenSearch client arguments.\n   * @returns Promise resolving to a new instance of OpenSearchVectorStore.\n   */\n  static async fromExistingIndex(\n    embeddings: EmbeddingsInterface,\n    dbConfig: OpenSearchClientArgs\n  ): Promise<OpenSearchVectorStore> {\n    const store = new OpenSearchVectorStore(embeddings, dbConfig);\n    await store.client.cat.indices({ index: store.indexName });\n    return store;\n  }\n\n  private async ensureIndexExists(\n    dimension: number,\n    engine = \"nmslib\",\n    spaceType = \"l2\",\n    efSearch = 512,\n    efConstruction = 512,\n    numberOfShards = 5,\n    numberOfReplicas = 1,\n    m = 16\n  ): Promise<void> {\n    const body = {\n      settings: {\n        index: {\n          number_of_shards: numberOfShards,\n          number_of_replicas: numberOfReplicas,\n          knn: true,\n          \"knn.algo_param.ef_search\": efSearch,\n        },\n      },\n      mappings: {\n        dynamic_templates: [\n          {\n            // map all metadata properties to be keyword\n            [`${this.metadataFieldName}.*`]: {\n              match_mapping_type: \"string\",\n              mapping: { type: \"keyword\" },\n            },\n          },\n          {\n            [`${this.metadataFieldName}.loc`]: {\n              match_mapping_type: \"object\",\n              mapping: { type: \"object\" },\n            },\n          },\n        ],\n        properties: {\n          [this.textFieldName]: { type: \"text\" },\n          [this.metadataFieldName]: { type: \"object\" },\n          [this.vectorFieldName]: {\n            type: \"knn_vector\",\n            dimension,\n            method: {\n              name: \"hnsw\",\n              engine,\n              space_type: spaceType,\n              parameters: { ef_construction: efConstruction, m },\n            },\n          },\n        },\n      },\n    };\n\n    const indexExists = await this.doesIndexExist();\n    if (indexExists) return;\n\n    await this.client.indices.create({ index: this.indexName, body });\n  }\n\n  /**\n   * Builds metadata terms for OpenSearch queries.\n   *\n   * This function takes a filter object and constructs an array of query terms\n   * compatible with OpenSearch 2.x. It supports a variety of query types including\n   * term, terms, terms_set, ids, range, prefix, exists, fuzzy, wildcard, and regexp.\n   * Reference: https://opensearch.org/docs/latest/query-dsl/term/index/\n   *\n   * @param {Filter | null} filter - The filter object used to construct query terms.\n   * Each key represents a field, and the value specifies the type of query and its parameters.\n   *\n   * @returns {Array<Record<string, any>>} An array of OpenSearch query terms.\n   *\n   * @example\n   * // Example filter:\n   * const filter = {\n   *   status: { \"exists\": true },\n   *   age: { \"gte\": 30, \"lte\": 40 },\n   *   tags: [\"tag1\", \"tag2\"],\n   *   description: { \"wildcard\": \"*test*\" },\n   *\n   * };\n   *\n   * // Resulting query terms:\n   * const queryTerms = buildMetadataTerms(filter);\n   * // queryTerms would be an array of OpenSearch query objects.\n   */\n  buildMetadataTerms(filter: OpenSearchFilter | undefined): object {\n    if (!filter) return {};\n    const must = [];\n    const must_not = [];\n    for (const [key, value] of Object.entries(filter)) {\n      const metadataKey = `${this.metadataFieldName}.${key}`;\n      if (value) {\n        if (typeof value === \"object\" && !Array.isArray(value)) {\n          if (\"exists\" in value) {\n            if (value.exists) {\n              must.push({ exists: { field: metadataKey } });\n            } else {\n              must_not.push({ exists: { field: metadataKey } });\n            }\n          } else if (\"fuzzy\" in value) {\n            must.push({ fuzzy: { [metadataKey]: value.fuzzy } });\n          } else if (\"ids\" in value) {\n            must.push({ ids: { values: value.ids } });\n          } else if (\"prefix\" in value) {\n            must.push({ prefix: { [metadataKey]: value.prefix } });\n          } else if (\n            \"gte\" in value ||\n            \"gt\" in value ||\n            \"lte\" in value ||\n            \"lt\" in value\n          ) {\n            must.push({ range: { [metadataKey]: value } });\n          } else if (\"regexp\" in value) {\n            must.push({ regexp: { [metadataKey]: value.regexp } });\n          } else if (\"terms_set\" in value) {\n            must.push({ terms_set: { [metadataKey]: value.terms_set } });\n          } else if (\"wildcard\" in value) {\n            must.push({ wildcard: { [metadataKey]: value.wildcard } });\n          }\n        } else {\n          const aggregatorKey = Array.isArray(value) ? \"terms\" : \"term\";\n          must.push({ [aggregatorKey]: { [metadataKey]: value } });\n        }\n      }\n    }\n    return { must, must_not };\n  }\n\n  /**\n   * Method to check if the OpenSearch index exists.\n   * @returns Promise resolving to a boolean indicating whether the index exists.\n   */\n  async doesIndexExist(): Promise<boolean> {\n    try {\n      await this.client.cat.indices({ index: this.indexName });\n      return true;\n    } catch (err: unknown) {\n      // eslint-disable-next-line no-instanceof/no-instanceof\n      if (err instanceof errors.ResponseError && err.statusCode === 404) {\n        return false;\n      }\n      throw err;\n    }\n  }\n\n  /**\n   * Method to delete the OpenSearch index if it exists.\n   * @returns Promise resolving to void.\n   */\n  async deleteIfExists(): Promise<void> {\n    const indexExists = await this.doesIndexExist();\n    if (!indexExists) return;\n\n    await this.client.indices.delete({ index: this.indexName });\n  }\n}\n"],"mappings":"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"}