UNPKG

@convo-lang/convo-lang

Version:
86 lines 3.58 kB
import { NotFoundError, httpClient, joinPaths } from "@iyio/common"; export class BaseOpenAiConvoCompletionService { constructor({ apiKey, secretManager, secretsName, apiBaseUrl = 'https://api.openai.com', completionsEndpoint = '/v1/chat/completions', inputType, outputType, models, isFallback = false, apiKeyHeader = 'Authorization', apiKeyHeaderValuePrefix = 'Bearer ', headers = { 'Content-Type': 'application/json' }, serviceId, logRequests = false, completeAsync, updateRequest, getModelsAsync, canComplete }) { this.clientPromises = {}; this.serviceId = serviceId; this.apiKey = apiKey; this.apiBaseUrl = apiBaseUrl; this.completionsEndpoint = completionsEndpoint; this.secretManager = secretManager; this.secretsName = secretsName; this.inputType = inputType; this.outputType = outputType; this.isFallback = isFallback; this.models = models; this.apiKeyHeader = apiKeyHeader; this.apiKeyHeaderValuePrefix = apiKeyHeaderValuePrefix ?? undefined; this.logRequests = logRequests; this.completeAsync = completeAsync; this.headers = headers; this.updateRequest = updateRequest; this._getModelsAsync = getModelsAsync; this._canComplete = canComplete; } canComplete(model, flat) { if (!model) { return this.isFallback; } if (this._canComplete) { return this._canComplete(model, flat); } return this.models?.some(m => m.name === model) ?? false; } async getApiClientAsync(apiKeyOverride, endpoint) { const url = endpoint ?? joinPaths(this.apiBaseUrl, this.completionsEndpoint); const key = `${url}:::${apiKeyOverride ?? '.'}`; return await (this.clientPromises[key] ?? (this.clientPromises[key] = (async () => { let apiKey = apiKeyOverride ?? this.apiKey; if (!apiKey && this.secretManager && this.secretsName) { const { apiKey: key } = await this.secretManager.requireSecretTAsync(this.secretsName, true); apiKey = key; } return { apiKey, url, }; })())); } async completeConvoAsync(input, flat, ctx) { const client = await this.getApiClientAsync(flat.apiKey ?? undefined, flat.responseEndpoint); if (flat.apiKey && flat.apiKey === client.apiKey) { flat.apiKeyUsedForCompletion = true; } const headers = { [this.apiKeyHeader]: client.apiKey ? ((this.apiKeyHeaderValuePrefix ?? '') + client.apiKey) : undefined, ...this.headers }; if (this.updateRequest) { input = { ...input }; this.updateRequest(input, headers); } await ctx.beforeComplete?.(this, input, flat); const r = await (this.completeAsync ? this.completeAsync(input, flat, client.apiKey, client.url) : httpClient().postAsync(client.url, input, { headers, readErrors: true, log: this.logRequests })); if (!r) { throw new NotFoundError(); } return r; } async getModelsAsync() { if (this.models) { return [...this.models]; } if (this._getModelsAsync) { return await this._getModelsAsync(); } return []; } } //# sourceMappingURL=BaseOpenAiConvoCompletionService.js.map