@microsoft/teams-ai
Version:
SDK focused on building AI based applications for Microsoft Teams.
166 lines • 6.67 kB
JavaScript
"use strict";
/**
* @module teams-ai
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAIEmbeddings = void 0;
const axios_1 = __importDefault(require("axios"));
const internals_1 = require("../internals");
/**
* A `EmbeddingsModel` for calling OpenAI and Azure OpenAI hosted models.
*/
class OpenAIEmbeddings {
_httpClient;
_useAzure;
UserAgent = '@microsoft/teams-ai-v1';
/**
* Options the client was configured with.
*/
options;
/**
* Creates a new `OpenAIEmbeddings` instance.
* @param {OpenAIEmbeddingsOptions | AzureOpenAIEmbeddingsOptions | OpenAILikeEmbeddingsOptions} options Options for configuring the embeddings client.
*/
constructor(options) {
// Check for azure config
if (options.azureApiKey) {
this._useAzure = true;
this.options = Object.assign({
retryPolicy: [2000, 5000],
azureApiVersion: '2023-05-15'
}, options);
// Cleanup and validate endpoint
let endpoint = this.options.azureEndpoint.trim();
if (endpoint.endsWith('/')) {
endpoint = endpoint.substring(0, endpoint.length - 1);
}
this.options.azureEndpoint = endpoint;
}
else {
this._useAzure = false;
this.options = Object.assign({
retryPolicy: [2000, 5000]
}, options);
}
// Create client
this._httpClient = axios_1.default.create({
validateStatus: (status) => status < 400 || status == 429
});
}
/**
* Creates embeddings for the given inputs using the OpenAI API.
* @param {string} model Name of the model to use (or deployment for Azure).
* @param {string | string[]} inputs Text inputs to create embeddings for.
* @returns {Promise<EmbeddingsResponse>} A `EmbeddingsResponse` with a status and the generated embeddings or a message when an error occurs.
*/
async createEmbeddings(model, inputs) {
if (this.options.logRequests) {
console.log(internals_1.Colorize.title('EMBEDDINGS REQUEST:'));
console.log(internals_1.Colorize.output(inputs));
}
const request = {
model: model,
input: inputs
};
if (this.options.dimensions) {
request.dimensions = this.options.dimensions;
}
const startTime = Date.now();
const response = await this.createEmbeddingRequest(request);
if (this.options.logRequests) {
console.log(internals_1.Colorize.title('RESPONSE:'));
console.log(internals_1.Colorize.value('status', response.status));
console.log(internals_1.Colorize.value('duration', Date.now() - startTime, 'ms'));
console.log(internals_1.Colorize.output(response.data));
}
// Process response
if (response.status < 300) {
return {
status: 'success',
output: response.data.data.sort((a, b) => a.index - b.index).map((item) => item.embedding)
};
}
else if (response.status == 429) {
return { status: 'rate_limited', message: `The embeddings API returned a rate limit error.` };
}
else {
return {
status: 'error',
message: `The embeddings API returned an error status of ${response.status}: ${response.statusText}`
};
}
}
/**
* @private
* @param {CreateEmbeddingRequest} request The request to send to the OpenAI API.
* @returns {Promise<AxiosResponse<CreateEmbeddingResponse>>} A promise that resolves to the response from the OpenAI API.
*/
createEmbeddingRequest(request) {
if (this._useAzure) {
const options = this.options;
const url = `${options.azureEndpoint}/openai/deployments/${options.azureDeployment}/embeddings?api-version=${options.azureApiVersion}`;
return this.post(url, request);
}
else {
const options = this.options;
const url = `${options.endpoint ?? 'https://api.openai.com'}/v1/embeddings`;
request.model = options.model;
return this.post(url, request);
}
}
/**
* @private
* @template TData Optional. Type of the data associated with the action.
* @param {string} url The URL to send the request to.
* @param {object} body The body of the request.
* @param {number} retryCount The number of times the request has been retried.
* @returns {Promise<AxiosResponse<TData>>} A promise that resolves to the response from the OpenAI API.
*/
async post(url, body, retryCount = 0) {
// Initialize request config
const requestConfig = Object.assign({}, this.options.requestConfig);
// Initialize request headers
if (!requestConfig.headers) {
requestConfig.headers = {};
}
if (!requestConfig.headers['Content-Type']) {
requestConfig.headers['Content-Type'] = 'application/json';
}
if (!requestConfig.headers['User-Agent']) {
requestConfig.headers['User-Agent'] = this.UserAgent;
}
if (this._useAzure) {
const options = this.options;
requestConfig.headers['api-key'] = options.azureApiKey;
}
else if (this.options.apiKey) {
const options = this.options;
requestConfig.headers['Authorization'] = `Bearer ${options.apiKey}`;
if (options.organization) {
requestConfig.headers['OpenAI-Organization'] = options.organization;
}
}
// Send request
const response = await this._httpClient.post(url, body, requestConfig);
// Check for rate limit error
if (response.status == 429 &&
Array.isArray(this.options.retryPolicy) &&
retryCount < this.options.retryPolicy.length) {
const delay = this.options.retryPolicy[retryCount];
await new Promise((resolve) => setTimeout(resolve, delay));
return this.post(url, body, retryCount + 1);
}
else {
return response;
}
}
}
exports.OpenAIEmbeddings = OpenAIEmbeddings;
//# sourceMappingURL=OpenAIEmbeddings.js.map