UNPKG

@robota-sdk/openai

Version:

OpenAI integration for Robota SDK - GPT-4, GPT-3.5, function calling, and tool integration with OpenAI's API

293 lines (287 loc) 9.66 kB
import OpenAI from 'openai'; import { ProviderOptions, BaseAIProvider, Context, ModelResponse, StreamingResponseChunk, UniversalMessage } from '@robota-sdk/core'; import { FunctionSchema } from '@robota-sdk/tools'; /** * OpenAI provider options */ interface OpenAIProviderOptions extends ProviderOptions { /** * Model name to use (default: gpt-3.5-turbo) */ model: string; /** * Temperature (0~1) */ temperature?: number; /** * Maximum number of tokens */ maxTokens?: number; /** * OpenAI API key (optional: not required when using client) */ apiKey?: string; /** * OpenAI organization ID (optional) */ organization?: string; /** * API request timeout (milliseconds) */ timeout?: number; /** * API base URL (default: 'https://api.openai.com/v1') */ baseURL?: string; /** * Response format (default: 'text') * - 'text': Plain text response * - 'json_object': Legacy JSON mode (requires system message) * - 'json_schema': Structured Outputs with schema validation */ responseFormat?: 'text' | 'json_object' | 'json_schema'; /** * JSON schema for structured outputs (required when responseFormat is 'json_schema') */ jsonSchema?: { name: string; description?: string; schema?: Record<string, unknown>; strict?: boolean; }; /** * OpenAI client instance (required) */ client: OpenAI; /** * Enable API payload logging to files * When enabled, saves API request payloads to log files * * @defaultValue false */ enablePayloadLogging?: boolean; /** * Directory path for storing API payload log files * * @defaultValue './logs/api-payloads' */ payloadLogDir?: string; /** * Include timestamp in payload log filenames * * @defaultValue true */ includeTimestampInLogFiles?: boolean; } /** * OpenAI AI provider implementation for Robota * * Provides integration with OpenAI's GPT models and other services. * Extends BaseAIProvider for common functionality and tool calling support. * * @see {@link ../../../apps/examples/03-integrations | Provider Integration Examples} * * @public */ declare class OpenAIProvider extends BaseAIProvider { /** * Provider identifier name * @readonly */ readonly name: string; /** * OpenAI client instance * @internal */ private readonly client; /** * Client type identifier * @readonly */ readonly type: string; /** * OpenAI client instance (alias for backwards compatibility) * @readonly * @deprecated Use the private client property instead */ readonly instance: OpenAI; /** * Provider configuration options * @readonly */ readonly options: OpenAIProviderOptions; /** * Payload logger for API request logging * @internal */ private readonly payloadLogger; /** * Create a new OpenAI provider instance * * @param options - Configuration options for the OpenAI provider * * @throws {Error} When client is not provided in options */ constructor(options: OpenAIProviderOptions); /** * Convert function definitions to OpenAI tool format * * Transforms universal function definitions into OpenAI's specific tool format * required by the Chat Completions API. * * @param functions - Array of universal function definitions * @returns Array of OpenAI-formatted tools */ formatFunctions(functions: FunctionSchema[]): OpenAI.Chat.ChatCompletionTool[]; /** * Filter conversation history for OpenAI API compatibility * * Converts messages to OpenAI format and filters out invalid tool messages. * * @param messages - Array of messages to filter * @returns OpenAI-formatted messages array */ private filterHistory; /** * Configure tools for OpenAI API request * * Transforms function schemas into OpenAI tool format and sets tool_choice. * * @param tools - Array of function schemas * @returns OpenAI tool configuration object */ protected configureTools(tools?: FunctionSchema[]): { tools: OpenAI.Chat.ChatCompletionTool[]; tool_choice: 'auto'; } | undefined; /** * Send a chat request to OpenAI and receive a complete response * * Processes the provided context and sends it to OpenAI's Chat Completions API. * Handles message format conversion, error handling, and response parsing. * * @param model - Model name to use (e.g., 'gpt-4', 'gpt-3.5-turbo') * @param context - Context object containing messages and system prompt * @param options - Optional generation parameters and tools * @returns Promise resolving to the model's response * * @throws {Error} When context is invalid * @throws {Error} When messages array is invalid * @throws {Error} When message format conversion fails * @throws {Error} When OpenAI API call fails */ chat(model: string, context: Context, options?: any): Promise<ModelResponse>; /** * Convert OpenAI API response to universal ModelResponse format * * Transforms the OpenAI-specific response format into the standard format * used across all providers in Robota. * * @param response - Raw response from OpenAI Chat Completions API * @returns Parsed model response in universal format * * @internal */ parseResponse(response: OpenAI.Chat.ChatCompletion): ModelResponse; /** * Convert OpenAI streaming response chunk to universal format * * Transforms individual chunks from OpenAI's streaming response into the * standard StreamingResponseChunk format used across all providers. * * @param chunk - Raw chunk from OpenAI streaming API * @returns Parsed streaming response chunk * * @internal */ parseStreamingChunk(chunk: OpenAI.Chat.ChatCompletionChunk): StreamingResponseChunk; /** * Send a streaming chat request to OpenAI and receive response chunks * * Similar to chat() but returns an async iterator that yields response chunks * as they arrive from OpenAI's streaming API. Useful for real-time display * of responses or handling large responses incrementally. * * @param model - Model name to use * @param context - Context object containing messages and system prompt * @param options - Optional generation parameters and tools * @returns Async generator yielding response chunks * * @throws {Error} When context is invalid * @throws {Error} When messages array is invalid * @throws {Error} When message format conversion fails * @throws {Error} When OpenAI streaming API call fails * * @see {@link ../../../apps/examples/01-basic | Basic Usage Examples} */ chatStream(model: string, context: Context, options?: any): AsyncGenerator<StreamingResponseChunk, void, unknown>; /** * Release resources and close connections * * Performs cleanup operations when the provider is no longer needed. * OpenAI client doesn't require explicit cleanup, so this is a no-op. * * @returns Promise that resolves when cleanup is complete */ close(): Promise<void>; } /** * OpenAI ConversationHistory adapter * * Converts UniversalMessage to OpenAI Chat Completions API format */ declare class OpenAIConversationAdapter { /** * Filter messages for OpenAI compatibility * * OpenAI has specific requirements: * - Tool messages must have valid toolCallId * - Messages must be in proper sequence * - Tool messages without toolCallId should be excluded */ static filterMessagesForOpenAI(messages: UniversalMessage[]): UniversalMessage[]; /** * Convert UniversalMessage array to OpenAI message format * Now properly handles tool messages for OpenAI's tool calling feature */ static toOpenAIFormat(messages: UniversalMessage[]): OpenAI.Chat.ChatCompletionMessageParam[]; /** * Convert a single UniversalMessage to OpenAI format * Handles all message types including tool messages */ static convertMessage(msg: UniversalMessage): OpenAI.Chat.ChatCompletionMessageParam; /** * Add system prompt to message array if needed */ static addSystemPromptIfNeeded(messages: OpenAI.Chat.ChatCompletionMessageParam[], systemPrompt?: string): OpenAI.Chat.ChatCompletionMessageParam[]; } /** * Utility class for logging OpenAI API payloads to files */ declare class PayloadLogger { private readonly enabled; private readonly logDir; private readonly includeTimestamp; constructor(enabled?: boolean, logDir?: string, includeTimestamp?: boolean); /** * Log API payload to file * @param payload - The API request payload * @param type - Type of request ('chat' or 'stream') */ logPayload(payload: any, type?: 'chat' | 'stream'): Promise<void>; /** * Ensure log directory exists */ private ensureLogDirectoryExists; /** * Sanitize payload to remove sensitive information * @param payload - Raw payload object * @returns Sanitized payload */ private sanitizePayload; /** * Check if logging is enabled */ isEnabled(): boolean; } export { OpenAIConversationAdapter, OpenAIProvider, type OpenAIProviderOptions, PayloadLogger };