UNPKG

@nomyx/assistant

Version:

A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)

162 lines (149 loc) 6.5 kB
import { ChatMessage, ChatOptions, ProviderResponse } from '../../../types/chat'; import { ProviderCapabilities, EmbeddingProvider } from '../../../types/provider'; import { Tool, GenericToolSchema, StandardizedToolCall } from '../../../types/tool'; import { ILogger } from '../../../types/common'; import { OpenAIProviderConfig } from './types'; import { OpenAIConfig } from './config'; import { chat } from './chat'; import { streamChat } from './streaming'; import { embed, embedBatch } from './embedding'; import { convertToolSchema, convertToolCall } from './tools'; import { BaseProvider } from '../BaseProvider'; import { OpenAICache } from './cache'; import { OpenAIProviderError, handleOpenAIError } from './errors'; /** * OpenAIProvider class that extends BaseProvider and implements EmbeddingProvider. * This provider interacts with the OpenAI API for various AI-related tasks. */ export class OpenAIProvider extends BaseProvider implements EmbeddingProvider { private config: OpenAIConfig; private cache: OpenAICache; /** * Creates an instance of OpenAIProvider. * @param {OpenAIProviderConfig} config - The configuration for the OpenAI provider. * @param {ILogger} logger - The logger instance for logging. */ constructor(config: OpenAIProviderConfig, logger: ILogger) { super(logger); this.config = new OpenAIConfig(config, logger); this.cache = new OpenAICache(); } /** * Sends a chat request to the OpenAI API. * @param {ChatMessage[]} messages - The chat messages to send. * @param {ChatOptions} options - The options for the chat request. * @param {Tool[]} [tools] - Optional tools to use in the chat. * @returns {Promise<ProviderResponse>} The response from the API. * @throws {OpenAIProviderError} If there's an error during the API call. */ async chat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): Promise<ProviderResponse> { try { const cacheKey = { messages, options, tools }; if (this.cache.has(cacheKey)) { this.logger.debug('Cache hit for chat request'); return this.cache.get(cacheKey)!; } const processedMessages = await this.applyMiddleware(messages); const response = await chat(this.config, processedMessages, options, tools); const processedResponse = await this.applyMiddlewareToResponse(response); if (processedResponse.toolCalls) { processedResponse.toolCalls = await this.applyMiddlewareToToolCalls(processedResponse.toolCalls); } this.cache.set(cacheKey, processedResponse); return processedResponse; } catch (error: unknown) { this.logger.error('Error in OpenAIProvider chat', { error: error instanceof Error ? error.message : String(error) }); throw handleOpenAIError(error); } } /** * Sends a streaming chat request to the OpenAI API. * @param {ChatMessage[]} messages - The chat messages to send. * @param {ChatOptions} options - The options for the chat request. * @param {Tool[]} [tools] - Optional tools to use in the chat. * @returns {AsyncIterableIterator<ProviderResponse>} An async iterator of responses from the API. * @throws {OpenAIProviderError} If there's an error during the API call. */ async *streamChat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): AsyncIterableIterator<ProviderResponse> { try { const processedMessages = await this.applyMiddleware(messages); for await (const response of streamChat(this.config, processedMessages, options, tools)) { const processedResponse = await this.applyMiddlewareToResponse(response); if (processedResponse.toolCalls) { processedResponse.toolCalls = await this.applyMiddlewareToToolCalls(processedResponse.toolCalls); } yield processedResponse; } } catch (error: unknown) { this.logger.error('Error in OpenAIProvider streamChat', { error: error instanceof Error ? error.message : String(error) }); throw handleOpenAIError(error); } } /** * Returns the capabilities of the OpenAI provider. * @returns {ProviderCapabilities} The capabilities of the provider. */ getCapabilities(): ProviderCapabilities { return { maxTokens: 4096, supportsFunctionCalling: true, supportsStreaming: true, supportedModels: ['gpt-4o', 'o1-preview'], maxSimultaneousCalls: 1, supportsSemanticCaching: false, }; } /** * Generates an embedding for the given text. * @param {string} text - The text to embed. * @returns {Promise<number[]>} The embedding as an array of numbers. * @throws {OpenAIProviderError} If there's an error during the API call. */ async embed(text: string): Promise<number[]> { try { return await embed(this.config, text); } catch (error: unknown) { this.logger.error('Error in OpenAIProvider embed', { error: error instanceof Error ? error.message : String(error) }); throw handleOpenAIError(error); } } /** * Generates embeddings for the given texts. * @param {string[]} texts - The texts to embed. * @returns {Promise<number[][]>} The embeddings as an array of number arrays. * @throws {OpenAIProviderError} If there's an error during the API call. */ async embedBatch(texts: string[]): Promise<number[][]> { try { return await embedBatch(this.config, texts); } catch (error: unknown) { this.logger.error('Error in OpenAIProvider embedBatch', { error: error instanceof Error ? error.message : String(error) }); throw handleOpenAIError(error); } } /** * Converts a generic tool schema to the OpenAI-specific format. * @param {GenericToolSchema} schema - The generic tool schema to convert. * @returns {any} The converted schema in OpenAI format. */ convertToolSchema(schema: GenericToolSchema): any { return convertToolSchema(schema); } /** * Converts an OpenAI tool call to the standardized format. * @param {any} call - The OpenAI tool call to convert. * @returns {StandardizedToolCall} The converted tool call in standardized format. */ convertToolCall(call: any): StandardizedToolCall { return convertToolCall(call); } /** * Clears the internal cache of the provider. */ clearCache(): void { this.cache.clear(); this.logger.debug('OpenAIProvider cache cleared'); } } export * from './types'; export { OpenAIProviderError } from './errors';