{"version":3,"file":"embeddings.cjs","names":["Embeddings","getEndpoint","getHeadersWithUserAgent","OpenAIClient","wrapOpenAIClientError"],"sources":["../src/embeddings.ts"],"sourcesContent":["import { type ClientOptions, OpenAI as OpenAIClient } from \"openai\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { Embeddings, type EmbeddingsParams } from \"@langchain/core/embeddings\";\nimport { chunkArray } from \"@langchain/core/utils/chunk_array\";\nimport type { OpenAIApiKey } from \"./types.js\";\nimport {\n  getEndpoint,\n  OpenAIEndpointConfig,\n  getHeadersWithUserAgent,\n} from \"./utils/azure.js\";\nimport { wrapOpenAIClientError } from \"./utils/client.js\";\n\n/**\n * @see https://platform.openai.com/docs/guides/embeddings#embedding-models\n */\nexport type OpenAIEmbeddingModelId =\n  | OpenAIClient.EmbeddingModel\n  | (string & NonNullable<unknown>);\n\n/**\n * Interface for OpenAIEmbeddings parameters. Extends EmbeddingsParams and\n * defines additional parameters specific to the OpenAIEmbeddings class.\n */\nexport interface OpenAIEmbeddingsParams extends EmbeddingsParams {\n  /**\n   * Model name to use\n   * Alias for `model`\n   * @deprecated Use \"model\" instead.\n   */\n  modelName: OpenAIEmbeddingModelId;\n  /** Model name to use */\n  model: OpenAIEmbeddingModelId;\n\n  /**\n   * The number of dimensions the resulting output embeddings should have.\n   * Only supported in `text-embedding-3` and later models.\n   */\n  dimensions?: number;\n\n  /**\n   * Timeout to use when making requests to OpenAI.\n   */\n  timeout?: number;\n\n  /**\n   * The maximum number of documents to embed in a single request. This is\n   * limited by the OpenAI API to a maximum of 2048.\n   */\n  batchSize?: number;\n\n  /**\n   * Whether to strip new lines from the input text. This is recommended by\n   * OpenAI for older models, but may not be suitable for all use cases.\n   * See: https://github.com/openai/openai-python/issues/418#issuecomment-1525939500\n   */\n  stripNewLines?: boolean;\n\n  /**\n   * The format to return the embeddings in. Can be either 'float' or 'base64'.\n   */\n  encodingFormat?: \"float\" | \"base64\";\n}\n\n/**\n * Class for generating embeddings using the OpenAI API.\n *\n * To use with Azure, import the `AzureOpenAIEmbeddings` class.\n *\n * @example\n * ```typescript\n * // Embed a query using OpenAIEmbeddings to generate embeddings for a given text\n * const model = new OpenAIEmbeddings();\n * const res = await model.embedQuery(\n *   \"What would be a good company name for a company that makes colorful socks?\",\n * );\n * console.log({ res });\n *\n * ```\n */\nexport class OpenAIEmbeddings<TOutput = number[]>\n  extends Embeddings<TOutput>\n  implements Partial<OpenAIEmbeddingsParams>\n{\n  model = \"text-embedding-ada-002\";\n\n  /** @deprecated Use \"model\" instead */\n  modelName: string;\n\n  batchSize = 512;\n\n  // TODO: Update to `false` on next minor release (see: https://github.com/langchain-ai/langchainjs/pull/3612)\n  stripNewLines = true;\n\n  /**\n   * The number of dimensions the resulting output embeddings should have.\n   * Only supported in `text-embedding-3` and later models.\n   */\n  dimensions?: number;\n\n  timeout?: number;\n\n  organization?: string;\n\n  encodingFormat?: \"float\" | \"base64\";\n\n  protected client: OpenAIClient;\n\n  protected clientConfig: ClientOptions;\n\n  protected apiKey?: OpenAIApiKey;\n\n  constructor(\n    fields?: Partial<OpenAIEmbeddingsParams> & {\n      verbose?: boolean;\n      /**\n       * The OpenAI API key to use.\n       * Alias for `apiKey`.\n       */\n      openAIApiKey?: OpenAIApiKey;\n      /** The OpenAI API key to use. */\n      apiKey?: OpenAIApiKey;\n      configuration?: ClientOptions;\n    }\n  ) {\n    const fieldsWithDefaults = { maxConcurrency: 2, ...fields };\n\n    super(fieldsWithDefaults);\n\n    const apiKey =\n      fieldsWithDefaults?.apiKey ??\n      fieldsWithDefaults?.openAIApiKey ??\n      getEnvironmentVariable(\"OPENAI_API_KEY\");\n\n    this.organization =\n      fieldsWithDefaults?.configuration?.organization ??\n      getEnvironmentVariable(\"OPENAI_ORGANIZATION\");\n\n    this.model =\n      fieldsWithDefaults?.model ?? fieldsWithDefaults?.modelName ?? this.model;\n    this.modelName = this.model;\n    this.batchSize = fieldsWithDefaults?.batchSize ?? this.batchSize;\n    this.stripNewLines =\n      fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;\n    this.timeout = fieldsWithDefaults?.timeout;\n    this.dimensions = fieldsWithDefaults?.dimensions;\n    this.encodingFormat = fieldsWithDefaults?.encodingFormat;\n\n    this.clientConfig = {\n      apiKey,\n      organization: this.organization,\n      dangerouslyAllowBrowser: true,\n      ...fields?.configuration,\n    };\n  }\n\n  /**\n   * Method to generate embeddings for an array of documents. Splits the\n   * documents into batches and makes requests to the OpenAI API to generate\n   * embeddings.\n   * @param texts Array of documents to generate embeddings for.\n   * @returns Promise that resolves to a 2D array of embeddings for each document.\n   */\n  async embedDocuments(texts: string[]): Promise<TOutput[]> {\n    const batches = chunkArray(\n      this.stripNewLines ? texts.map((t) => t.replace(/\\n/g, \" \")) : texts,\n      this.batchSize\n    );\n\n    const batchRequests = batches.map((batch) => {\n      const params: OpenAIClient.EmbeddingCreateParams = {\n        model: this.model,\n        input: batch,\n      };\n      if (this.dimensions) {\n        params.dimensions = this.dimensions;\n      }\n      if (this.encodingFormat) {\n        params.encoding_format = this.encodingFormat;\n      }\n      return this.embeddingWithRetry(params);\n    });\n    const batchResponses = await Promise.all(batchRequests);\n\n    const embeddings: TOutput[] = [];\n    for (let i = 0; i < batchResponses.length; i += 1) {\n      const batch = batches[i];\n      const { data: batchResponse } = batchResponses[i];\n      for (let j = 0; j < batch.length; j += 1) {\n        embeddings.push(batchResponse[j].embedding as TOutput);\n      }\n    }\n    return embeddings;\n  }\n\n  /**\n   * Method to generate an embedding for a single document. Calls the\n   * embeddingWithRetry method with the document as the input.\n   * @param text Document to generate an embedding for.\n   * @returns Promise that resolves to an embedding for the document.\n   */\n  async embedQuery(text: string): Promise<TOutput> {\n    const params: OpenAIClient.EmbeddingCreateParams = {\n      model: this.model,\n      input: this.stripNewLines ? text.replace(/\\n/g, \" \") : text,\n    };\n    if (this.dimensions) {\n      params.dimensions = this.dimensions;\n    }\n    if (this.encodingFormat) {\n      params.encoding_format = this.encodingFormat;\n    }\n    const { data } = await this.embeddingWithRetry(params);\n    return data[0].embedding as TOutput;\n  }\n\n  /**\n   * Private method to make a request to the OpenAI API to generate\n   * embeddings. Handles the retry logic and returns the response from the\n   * API.\n   * @param request Request to send to the OpenAI API.\n   * @returns Promise that resolves to the response from the API.\n   */\n  protected async embeddingWithRetry(\n    request: OpenAIClient.EmbeddingCreateParams\n  ) {\n    if (!this.client) {\n      const openAIEndpointConfig: OpenAIEndpointConfig = {\n        baseURL: this.clientConfig.baseURL,\n      };\n\n      const endpoint = getEndpoint(openAIEndpointConfig);\n\n      const params = {\n        ...this.clientConfig,\n        baseURL: endpoint,\n        timeout: this.timeout,\n        maxRetries: 0,\n      };\n\n      if (!params.baseURL) {\n        delete params.baseURL;\n      }\n\n      params.defaultHeaders = getHeadersWithUserAgent(params.defaultHeaders);\n\n      this.client = new OpenAIClient(params);\n    }\n    const requestOptions = {};\n\n    return this.caller.call(async () => {\n      try {\n        const res = await this.client.embeddings.create(\n          request,\n          requestOptions\n        );\n        return res;\n      } catch (e) {\n        const error = wrapOpenAIClientError(e);\n        throw error;\n      }\n    });\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA+EA,IAAa,mBAAb,cACUA,2BAAAA,WAEV;CACE,QAAQ;;CAGR;CAEA,YAAY;CAGZ,gBAAgB;;;;;CAMhB;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA,YACE,QAWA;EACA,MAAM,qBAAqB;GAAE,gBAAgB;GAAG,GAAG;GAAQ;AAE3D,QAAM,mBAAmB;EAEzB,MAAM,SACJ,oBAAoB,UACpB,oBAAoB,iBAAA,GAAA,0BAAA,wBACG,iBAAiB;AAE1C,OAAK,eACH,oBAAoB,eAAe,iBAAA,GAAA,0BAAA,wBACZ,sBAAsB;AAE/C,OAAK,QACH,oBAAoB,SAAS,oBAAoB,aAAa,KAAK;AACrE,OAAK,YAAY,KAAK;AACtB,OAAK,YAAY,oBAAoB,aAAa,KAAK;AACvD,OAAK,gBACH,oBAAoB,iBAAiB,KAAK;AAC5C,OAAK,UAAU,oBAAoB;AACnC,OAAK,aAAa,oBAAoB;AACtC,OAAK,iBAAiB,oBAAoB;AAE1C,OAAK,eAAe;GAClB;GACA,cAAc,KAAK;GACnB,yBAAyB;GACzB,GAAG,QAAQ;GACZ;;;;;;;;;CAUH,MAAM,eAAe,OAAqC;EACxD,MAAM,WAAA,GAAA,kCAAA,YACJ,KAAK,gBAAgB,MAAM,KAAK,MAAM,EAAE,QAAQ,OAAO,IAAI,CAAC,GAAG,OAC/D,KAAK,UACN;EAED,MAAM,gBAAgB,QAAQ,KAAK,UAAU;GAC3C,MAAM,SAA6C;IACjD,OAAO,KAAK;IACZ,OAAO;IACR;AACD,OAAI,KAAK,WACP,QAAO,aAAa,KAAK;AAE3B,OAAI,KAAK,eACP,QAAO,kBAAkB,KAAK;AAEhC,UAAO,KAAK,mBAAmB,OAAO;IACtC;EACF,MAAM,iBAAiB,MAAM,QAAQ,IAAI,cAAc;EAEvD,MAAM,aAAwB,EAAE;AAChC,OAAK,IAAI,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK,GAAG;GACjD,MAAM,QAAQ,QAAQ;GACtB,MAAM,EAAE,MAAM,kBAAkB,eAAe;AAC/C,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,EACrC,YAAW,KAAK,cAAc,GAAG,UAAqB;;AAG1D,SAAO;;;;;;;;CAST,MAAM,WAAW,MAAgC;EAC/C,MAAM,SAA6C;GACjD,OAAO,KAAK;GACZ,OAAO,KAAK,gBAAgB,KAAK,QAAQ,OAAO,IAAI,GAAG;GACxD;AACD,MAAI,KAAK,WACP,QAAO,aAAa,KAAK;AAE3B,MAAI,KAAK,eACP,QAAO,kBAAkB,KAAK;EAEhC,MAAM,EAAE,SAAS,MAAM,KAAK,mBAAmB,OAAO;AACtD,SAAO,KAAK,GAAG;;;;;;;;;CAUjB,MAAgB,mBACd,SACA;AACA,MAAI,CAAC,KAAK,QAAQ;GAKhB,MAAM,WAAWC,cAAAA,YAJkC,EACjD,SAAS,KAAK,aAAa,SAC5B,CAEiD;GAElD,MAAM,SAAS;IACb,GAAG,KAAK;IACR,SAAS;IACT,SAAS,KAAK;IACd,YAAY;IACb;AAED,OAAI,CAAC,OAAO,QACV,QAAO,OAAO;AAGhB,UAAO,iBAAiBC,cAAAA,wBAAwB,OAAO,eAAe;AAEtE,QAAK,SAAS,IAAIC,OAAAA,OAAa,OAAO;;EAExC,MAAM,iBAAiB,EAAE;AAEzB,SAAO,KAAK,OAAO,KAAK,YAAY;AAClC,OAAI;AAKF,WAJY,MAAM,KAAK,OAAO,WAAW,OACvC,SACA,eACD;YAEM,GAAG;AAEV,UADcC,eAAAA,sBAAsB,EAAE;;IAGxC"}