UNPKG

bb-inspired

Version:

Core library for BB-inspired NestJS backend

242 lines 10.2 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var OpenAIService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenAIService = void 0; const common_1 = require("@nestjs/common"); const openai_1 = require("openai"); let OpenAIService = OpenAIService_1 = class OpenAIService { constructor(config) { this.logger = new common_1.Logger(OpenAIService_1.name); if (!config.apiKey) { throw new Error('OpenAI API key is required'); } this.client = new openai_1.OpenAI({ apiKey: config.apiKey, organization: config.organization, baseURL: config.baseUrl, timeout: config.timeout || 30000, maxRetries: config.maxRetries || 3, }); this.defaultModel = config.defaultModel || 'gpt-4'; this.logger.log(`OpenAI service initialized with default model: ${this.defaultModel}`); } async listModels() { try { const response = await this.client.models.list(); return response.data.map(model => ({ id: model.id, created: model.created, ownedBy: model.owned_by, maxContextLength: this.getModelContextLength(model.id), supportsFunctionCalling: this.supportsFunctionCalling(model.id), })); } catch (error) { this.logger.error(`Error listing models: ${error.message}`, error.stack); throw new Error(`Failed to list models: ${error.message}`); } } async getModel(modelId) { try { const model = await this.client.models.retrieve(modelId); return { id: model.id, created: model.created, ownedBy: model.owned_by, maxContextLength: this.getModelContextLength(model.id), supportsFunctionCalling: this.supportsFunctionCalling(model.id), }; } catch (error) { this.logger.error(`Error retrieving model ${modelId}: ${error.message}`, error.stack); throw new Error(`Failed to retrieve model ${modelId}: ${error.message}`); } } async createCompletion(prompt, options = {}) { var _a, _b, _c, _d, _e; try { const model = options.model || this.defaultModel; const messages = [ { role: 'user', content: prompt } ]; const response = await this.client.chat.completions.create({ model, messages, max_tokens: options.maxTokens, temperature: options.temperature, top_p: options.topP, presence_penalty: options.presencePenalty, frequency_penalty: options.frequencyPenalty, stop: options.stop, stream: false, }); const result = { text: ((_b = (_a = response.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) || '', usage: { promptTokens: ((_c = response.usage) === null || _c === void 0 ? void 0 : _c.prompt_tokens) || 0, completionTokens: ((_d = response.usage) === null || _d === void 0 ? void 0 : _d.completion_tokens) || 0, totalTokens: ((_e = response.usage) === null || _e === void 0 ? void 0 : _e.total_tokens) || 0, }, }; return result; } catch (error) { this.logger.error(`Error creating completion: ${error.message}`, error.stack); throw new Error(`Failed to create completion: ${error.message}`); } } async createChatCompletion(options) { var _a, _b, _c, _d, _e, _f, _g; try { const model = options.model || this.defaultModel; const messages = options.messages.map(msg => { if (msg.role === 'function') { return { role: msg.role, content: msg.content, name: msg.name || 'function' }; } return { role: msg.role, content: msg.content, ...(msg.name ? { name: msg.name } : {}) }; }); let functions; if (options.functions && options.functions.length > 0) { functions = options.functions.map(fn => ({ name: fn.name, description: fn.description, parameters: fn.parameters })); } let function_call; if (options.functionCall) { if (typeof options.functionCall === 'string') { function_call = options.functionCall; } else { function_call = { name: options.functionCall.name }; } } if (options.stream) { throw new Error('Streaming is not supported in createChatCompletion'); } const response = await this.client.chat.completions.create({ model, messages, functions, function_call, max_tokens: options.maxTokens, temperature: options.temperature, top_p: options.topP, presence_penalty: options.presencePenalty, frequency_penalty: options.frequencyPenalty, stop: options.stop, stream: false, }); const message = { role: 'assistant', content: ((_b = (_a = response.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) || '', }; if ((_d = (_c = response.choices[0]) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.function_call) { message.functionCall = { name: response.choices[0].message.function_call.name, arguments: response.choices[0].message.function_call.arguments, }; } const result = { message, usage: { promptTokens: ((_e = response.usage) === null || _e === void 0 ? void 0 : _e.prompt_tokens) || 0, completionTokens: ((_f = response.usage) === null || _f === void 0 ? void 0 : _f.completion_tokens) || 0, totalTokens: ((_g = response.usage) === null || _g === void 0 ? void 0 : _g.total_tokens) || 0, }, }; return result; } catch (error) { this.logger.error(`Error creating chat completion: ${error.message}`, error.stack); throw new Error(`Failed to create chat completion: ${error.message}`); } } async createEmbedding(input, options = {}) { try { const inputArray = Array.isArray(input) ? input : [input]; const model = options.model || 'text-embedding-ada-002'; const embeddings = await this.client.embeddings.create({ model, input: inputArray, user: options.user, }); const result = { embeddings: embeddings.data.map(item => item.embedding), usage: { promptTokens: embeddings.usage.prompt_tokens, totalTokens: embeddings.usage.total_tokens, }, }; return result; } catch (error) { this.logger.error(`Error creating embeddings: ${error.message}`, error.stack); throw new Error(`Failed to create embeddings: ${error.message}`); } } estimateTokenCount(text) { return Math.ceil(text.length / 4); } getModelContextLength(modelId) { const modelContextLengths = { 'gpt-4': 8192, 'gpt-4-32k': 32768, 'gpt-4-turbo': 128000, 'gpt-3.5-turbo': 4096, 'gpt-3.5-turbo-16k': 16384, 'text-embedding-ada-002': 8191, }; if (modelContextLengths[modelId]) { return modelContextLengths[modelId]; } for (const [model, length] of Object.entries(modelContextLengths)) { if (modelId.startsWith(model)) { return length; } } return undefined; } supportsFunctionCalling(modelId) { const functionCallingModels = [ 'gpt-4', 'gpt-4-32k', 'gpt-4-turbo', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', ]; for (const model of functionCallingModels) { if (modelId.startsWith(model)) { return true; } } return false; } }; exports.OpenAIService = OpenAIService; exports.OpenAIService = OpenAIService = OpenAIService_1 = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [Object]) ], OpenAIService); //# sourceMappingURL=openai.service.js.map