All files / src/providers/openai Embedding.ts

77.27% Statements 17/22
42.85% Branches 6/14
80% Functions 4/5
76.19% Lines 16/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                    44x 44x               4x           4x   4x   4x         4x       4x       4x 4x   4x                         4x       4x 4x             6x   4x                
import { EmbeddingRequest, EmbeddingResponse } from "../Provider.js";
import { handleOpenAIError } from "./Errors.js";
import { Capabilities } from "./Capabilities.js";
import { DEFAULT_MODELS } from "../../constants.js";
import { buildUrl } from "./utils.js";
import { logger } from "../../utils/logger.js";
import { fetchWithTimeout } from "../../utils/fetch.js";
 
export class OpenAIEmbedding {
  constructor(
    protected readonly baseUrl: string,
    protected readonly apiKey: string
  ) {}
 
  protected getProviderName(): string {
    return "openai";
  }
 
  protected validateModel(model: string): void {
    Iif (Capabilities.getModelType(model) !== "embeddings") {
      throw new Error(`Model ${model} does not support embeddings.`);
    }
  }
 
  async execute(request: EmbeddingRequest): Promise<EmbeddingResponse> {
    const model = request.model || DEFAULT_MODELS.EMBEDDING;
 
    this.validateModel(model);
 
    const body: Record<string, unknown> = {
      input: request.input,
      model
    };
 
    Iif (request.dimensions) {
      body.dimensions = request.dimensions;
    }
 
    Iif (request.user) {
      body.user = request.user;
    }
 
    const url = buildUrl(this.baseUrl, "/embeddings");
    logger.logRequest("OpenAI", "POST", url, body);
 
    const response = await fetchWithTimeout(
      url,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${this.apiKey}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify(body)
      },
      request.requestTimeout
    );
 
    Iif (!response.ok) {
      await handleOpenAIError(response, request.model || DEFAULT_MODELS.EMBEDDING);
    }
 
    const { data, model: responseModel, usage } = await response.json();
    logger.logResponse("OpenAI", response.status, response.statusText, {
      data,
      model: responseModel,
      usage
    });
 
    // Extract vectors from the response
    const vectors = data.map((item: { embedding: number[] }) => item.embedding);
 
    return {
      vectors,
      model: responseModel,
      input_tokens: usage.prompt_tokens,
      dimensions: vectors[0]?.length || 0
    };
  }
}