@memberjunction/ai-openai 3.4.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/readme.md CHANGED
@@ -1,20 +1,58 @@
1
1
  # @memberjunction/ai-openai
2
2
 
3
- A comprehensive wrapper for OpenAI's API and models that seamlessly integrates with the MemberJunction AI framework, providing a standardized interface for GPT, embedding, and text-to-speech models.
3
+ MemberJunction AI provider for OpenAI. This is the foundational LLM provider in MemberJunction, implementing `BaseLLM` and `BaseEmbeddings` from `@memberjunction/ai`. Many other providers (Groq, Cerebras, Fireworks, OpenRouter, LMStudio, xAI) extend this package since they use OpenAI-compatible APIs.
4
+
5
+ ## Architecture
6
+
7
+ ```mermaid
8
+ graph TD
9
+ A["OpenAILLM<br/>(Provider)"] -->|extends| B["BaseLLM<br/>(@memberjunction/ai)"]
10
+ C["OpenAIEmbedding<br/>(Provider)"] -->|extends| D["BaseEmbeddings<br/>(@memberjunction/ai)"]
11
+ A -->|wraps| E["OpenAI SDK<br/>(openai npm)"]
12
+ C -->|wraps| E
13
+ A -->|provides| F["Chat + Streaming"]
14
+ A -->|provides| G["Thinking Extraction"]
15
+ A -->|provides| H["JSON / Response<br/>Format Control"]
16
+ B -->|registered via| I["@RegisterClass"]
17
+ D -->|registered via| I
18
+
19
+ subgraph Subclasses["OpenAI-Compatible Subclasses"]
20
+ J["GroqLLM"]
21
+ K["CerebrasLLM"]
22
+ L["FireworksLLM"]
23
+ M["OpenRouterLLM"]
24
+ N["LMStudioLLM"]
25
+ O["xAILLM"]
26
+ end
27
+ J -->|extends| A
28
+ K -->|extends| A
29
+ L -->|extends| A
30
+ M -->|extends| A
31
+ N -->|extends| A
32
+ O -->|extends| A
33
+
34
+ style A fill:#7c5295,stroke:#563a6b,color:#fff
35
+ style C fill:#7c5295,stroke:#563a6b,color:#fff
36
+ style B fill:#2d6a9f,stroke:#1a4971,color:#fff
37
+ style D fill:#2d6a9f,stroke:#1a4971,color:#fff
38
+ style E fill:#2d8659,stroke:#1a5c3a,color:#fff
39
+ style F fill:#b8762f,stroke:#8a5722,color:#fff
40
+ style G fill:#b8762f,stroke:#8a5722,color:#fff
41
+ style H fill:#b8762f,stroke:#8a5722,color:#fff
42
+ style I fill:#b8762f,stroke:#8a5722,color:#fff
43
+ ```
4
44
 
5
45
  ## Features
6
46
 
7
- - **OpenAI Integration**: Full integration with OpenAI's chat completion, embedding, and TTS models
8
- - **Standardized Interface**: Follows MemberJunction's BaseLLM, BaseEmbeddings, and BaseAudioGenerator abstract classes
9
- - **Streaming Support**: Full support for streaming chat completions
10
- - **Message Formatting**: Handles conversion between MemberJunction and OpenAI message formats
11
- - **Multi-modal Support**: Supports text and image content in messages
12
- - **Response Format Support**: Support for different response formats (Text, JSON, Markdown, ModelSpecific)
13
- - **Reasoning Models**: Support for reasoning effort levels (o1 models)
14
- - **Error Handling**: Comprehensive error handling with detailed reporting
15
- - **Token Usage Tracking**: Automatic tracking of prompt and completion tokens
16
- - **Embeddings**: Text embedding generation with multiple models
17
- - **Text-to-Speech**: Generate speech from text using OpenAI's TTS models
47
+ - **Chat Completions**: Full support for GPT-4, GPT-4o, o1, o3, and other OpenAI models
48
+ - **Streaming**: Real-time response streaming with chunk processing
49
+ - **Thinking/Reasoning**: Extraction of thinking content from `<think>` blocks in reasoning model responses
50
+ - **Embeddings**: Text embedding generation via OpenAI embedding models
51
+ - **Multimodal Input**: Support for text and image content in messages
52
+ - **Response Formats**: JSON mode, text, and other format controls
53
+ - **Effort Level**: Maps MJ effort levels to OpenAI reasoning effort parameters
54
+ - **Error Analysis**: Integrated error analysis via `ErrorAnalyzer`
55
+ - **Extensible Base**: Designed as the foundation for OpenAI-compatible providers
18
56
 
19
57
  ## Installation
20
58
 
@@ -22,351 +60,105 @@ A comprehensive wrapper for OpenAI's API and models that seamlessly integrates w
22
60
  npm install @memberjunction/ai-openai
23
61
  ```
24
62
 
25
- ## Requirements
26
-
27
- - Node.js 16+
28
- - An OpenAI API key
29
- - MemberJunction Core libraries
30
-
31
63
  ## Usage
32
64
 
33
- ### Basic Setup
65
+ ### Chat Completion
34
66
 
35
67
  ```typescript
36
68
  import { OpenAILLM } from '@memberjunction/ai-openai';
37
69
 
38
- // Initialize with your API key
39
- const openAI = new OpenAILLM('your-openai-api-key');
40
- ```
70
+ const llm = new OpenAILLM('your-openai-api-key');
41
71
 
42
- ### Chat Completion
72
+ const result = await llm.ChatCompletion({
73
+ model: 'gpt-4o',
74
+ messages: [
75
+ { role: 'system', content: 'You are a helpful assistant.' },
76
+ { role: 'user', content: 'Explain quantum computing.' }
77
+ ],
78
+ temperature: 0.7,
79
+ maxOutputTokens: 1000
80
+ });
43
81
 
44
- ```typescript
45
- import { ChatParams } from '@memberjunction/ai';
46
-
47
- // Create chat parameters
48
- const chatParams: ChatParams = {
49
- model: 'gpt-4',
50
- messages: [
51
- { role: 'system', content: 'You are a helpful assistant.' },
52
- { role: 'user', content: 'What is machine learning?' }
53
- ],
54
- temperature: 0.7,
55
- maxOutputTokens: 500,
56
- responseFormat: 'Text',
57
- includeLogProbs: false
58
- };
59
-
60
- // Get a response
61
- try {
62
- const response = await openAI.ChatCompletion(chatParams);
63
- if (response.success) {
64
- console.log('Response:', response.data.choices[0].message.content);
65
- console.log('Token Usage:', response.data.usage);
66
- } else {
67
- console.error('Error:', response.errorMessage);
68
- }
69
- } catch (error) {
70
- console.error('Exception:', error);
82
+ if (result.success) {
83
+ console.log(result.data.choices[0].message.content);
71
84
  }
72
85
  ```
73
86
 
74
- ### Streaming Chat Completion
75
-
76
- ```typescript
77
- const streamingParams: ChatParams = {
78
- model: 'gpt-4',
79
- messages: [
80
- { role: 'user', content: 'Tell me a story' }
81
- ],
82
- temperature: 0.8,
83
- maxOutputTokens: 1000
84
- };
85
-
86
- // Stream the response
87
- await openAI.StreamingChatCompletion(streamingParams, {
88
- onStart: () => console.log('Streaming started...'),
89
- onContent: (content) => process.stdout.write(content),
90
- onComplete: (fullContent) => console.log('\n\nComplete:', fullContent),
91
- onError: (error) => console.error('Error:', error),
92
- onUsage: (usage) => console.log('Token usage:', usage)
93
- });
94
- ```
95
-
96
- ### Multi-modal Messages (Text + Images)
87
+ ### Streaming
97
88
 
98
89
  ```typescript
99
- const multiModalParams: ChatParams = {
100
- model: 'gpt-4-vision-preview',
101
- messages: [
102
- {
103
- role: 'user',
104
- content: [
105
- { type: 'text', content: 'What do you see in this image?' },
106
- { type: 'image_url', content: 'https://example.com/image.jpg' }
107
- ]
90
+ const result = await llm.ChatCompletion({
91
+ model: 'gpt-4o',
92
+ messages: [{ role: 'user', content: 'Write a detailed essay.' }],
93
+ streaming: true,
94
+ streamingCallbacks: {
95
+ OnContent: (content) => process.stdout.write(content),
96
+ OnComplete: (result) => console.log('\nDone!')
108
97
  }
109
- ],
110
- maxOutputTokens: 500
111
- };
112
-
113
- const response = await openAI.ChatCompletion(multiModalParams);
114
- ```
115
-
116
- ### JSON Response Format
117
-
118
- ```typescript
119
- const jsonParams: ChatParams = {
120
- model: 'gpt-4',
121
- messages: [
122
- { role: 'system', content: 'You are a helpful assistant that outputs JSON.' },
123
- { role: 'user', content: 'Generate a JSON object with name, age, and city for 3 fictional people.' }
124
- ],
125
- temperature: 0.3,
126
- maxOutputTokens: 500,
127
- responseFormat: 'JSON'
128
- };
129
-
130
- const jsonResponse = await openAI.ChatCompletion(jsonParams);
131
- const jsonData = JSON.parse(jsonResponse.data.choices[0].message.content);
132
- console.log('Structured Data:', jsonData);
133
- ```
134
-
135
- ### Reasoning Models (o1 series)
136
-
137
- ```typescript
138
- const reasoningParams: ChatParams = {
139
- model: 'o1-preview',
140
- messages: [
141
- { role: 'user', content: 'Solve this complex math problem...' }
142
- ],
143
- effortLevel: 'high', // 'low', 'medium', or 'high'
144
- maxOutputTokens: 2000
145
- };
146
-
147
- const response = await openAI.ChatCompletion(reasoningParams);
148
- ```
149
-
150
- ### Text Summarization
151
-
152
- ```typescript
153
- import { SummarizeParams } from '@memberjunction/ai';
154
-
155
- const text = `Long text that you want to summarize...`;
156
-
157
- const summarizeParams: SummarizeParams = {
158
- text: text,
159
- model: 'gpt-3.5-turbo',
160
- temperature: 0.3,
161
- maxWords: 100
162
- };
163
-
164
- const summary = await openAI.SummarizeText(summarizeParams);
165
- console.log('Summary:', summary.summary);
166
- ```
167
-
168
- ### Text Embeddings
169
-
170
- ```typescript
171
- import { OpenAIEmbedding } from '@memberjunction/ai-openai';
172
-
173
- const embedding = new OpenAIEmbedding('your-openai-api-key');
174
-
175
- // Embed a single text
176
- const singleResult = await embedding.EmbedText({
177
- text: 'The quick brown fox jumps over the lazy dog',
178
- model: 'text-embedding-3-small' // or 'text-embedding-3-large', 'text-embedding-ada-002'
179
98
  });
180
- console.log('Embedding vector:', singleResult.vector);
181
-
182
- // Embed multiple texts
183
- const multiResult = await embedding.EmbedTexts({
184
- texts: ['First text', 'Second text', 'Third text'],
185
- model: 'text-embedding-3-large'
186
- });
187
- console.log('Embedding vectors:', multiResult.vectors);
188
-
189
- // Get available models
190
- const models = await embedding.GetEmbeddingModels();
191
- console.log('Available models:', models);
192
99
  ```
193
100
 
194
- ### Text-to-Speech
101
+ ### Embeddings
195
102
 
196
103
  ```typescript
197
- import { OpenAIAudioGenerator } from '@memberjunction/ai-openai';
198
-
199
- const tts = new OpenAIAudioGenerator('your-openai-api-key');
200
-
201
- // Generate speech
202
- const speechResult = await tts.CreateSpeech({
203
- text: 'Hello, this is a test of OpenAI text-to-speech.',
204
- model_id: 'gpt-4o-mini-tts',
205
- voice: 'nova', // 'alloy', 'echo', 'fable', 'onyx', 'nova', or 'shimmer'
206
- instructions: 'Speak in a cheerful and positive tone'
207
- });
208
-
209
- if (speechResult.success) {
210
- // speechResult.data contains the audio buffer
211
- // speechResult.content contains base64-encoded audio
212
- fs.writeFileSync('output.mp3', speechResult.data);
213
- }
214
-
215
- // Get available voices and models
216
- const voices = await tts.GetVoices();
217
- const models = await tts.GetModels();
218
- ```
104
+ import { OpenAIEmbedding } from '@memberjunction/ai-openai';
219
105
 
220
- ### Direct Access to OpenAI Client
106
+ const embedder = new OpenAIEmbedding('your-openai-api-key');
221
107
 
222
- ```typescript
223
- // Access the underlying OpenAI client for advanced usage
224
- const openAIClient = openAI.OpenAI;
225
-
226
- // Use the client directly for features not wrapped
227
- const completion = await openAIClient.completions.create({
228
- model: 'gpt-3.5-turbo-instruct',
229
- prompt: 'Say this is a test',
230
- max_tokens: 7
108
+ const result = await embedder.EmbedText({
109
+ text: 'Sample text for embedding',
110
+ model: 'text-embedding-3-small'
231
111
  });
232
- ```
233
-
234
- ## API Reference
235
-
236
- ### OpenAILLM Class
237
-
238
- Extends `BaseLLM` to provide OpenAI-specific chat and completion functionality.
239
-
240
- #### Constructor
241
- ```typescript
242
- new OpenAILLM(apiKey: string)
243
- ```
244
112
 
245
- #### Properties
246
- - `OpenAI`: (read-only) Returns the underlying OpenAI client instance
247
- - `SupportsStreaming`: (read-only) Returns `true` - OpenAI supports streaming
248
-
249
- #### Methods
250
- - `ChatCompletion(params: ChatParams): Promise<ChatResult>` - Perform a chat completion
251
- - `StreamingChatCompletion(params: ChatParams, callbacks: StreamingChatCallbacks): Promise<void>` - Stream a chat completion
252
- - `SummarizeText(params: SummarizeParams): Promise<SummarizeResult>` - Summarize text
253
- - `ClassifyText(params: ClassifyParams): Promise<ClassifyResult>` - Classify text (not implemented)
254
- - `ConvertMJToOpenAIChatMessages(messages: ChatMessage[]): ChatCompletionMessageParam[]` - Convert MJ to OpenAI format
255
- - `ConvertMJToOpenAIRole(role: string): 'system' | 'user' | 'assistant'` - Convert MJ roles to OpenAI roles
256
-
257
- ### OpenAIEmbedding Class
258
-
259
- Extends `BaseEmbeddings` to provide OpenAI embedding functionality.
260
-
261
- #### Constructor
262
- ```typescript
263
- new OpenAIEmbedding(apiKey: string)
264
- ```
265
-
266
- #### Methods
267
- - `EmbedText(params: EmbedTextParams): Promise<EmbedTextResult>` - Generate embedding for single text
268
- - `EmbedTexts(params: EmbedTextsParams): Promise<EmbedTextsResult>` - Generate embeddings for multiple texts
269
- - `GetEmbeddingModels(): Promise<any>` - Get available embedding models
270
-
271
- ### OpenAIAudioGenerator Class
272
-
273
- Extends `BaseAudioGenerator` to provide OpenAI text-to-speech functionality.
274
-
275
- #### Constructor
276
- ```typescript
277
- new OpenAIAudioGenerator(apiKey: string)
113
+ console.log(`Dimensions: ${result.vector.length}`);
278
114
  ```
279
115
 
280
- #### Methods
281
- - `CreateSpeech(params: TextToSpeechParams): Promise<SpeechResult>` - Generate speech from text
282
- - `SpeechToText(params: SpeechToTextParams): Promise<SpeechResult>` - Convert speech to text (not implemented)
283
- - `GetVoices(): Promise<VoiceInfo[]>` - Get available voices
284
- - `GetModels(): Promise<AudioModel[]>` - Get available TTS models
285
- - `GetPronounciationDictionaries(): Promise<PronounciationDictionary[]>` - Get pronunciation dictionaries (empty)
286
- - `GetSupportedMethods(): Promise<string[]>` - Get supported methods
287
-
288
- ## Embedding Models
289
-
290
- - **text-embedding-3-large**: Most capable model (3,072 dimensions)
291
- - **text-embedding-3-small**: Balanced performance (1,536 dimensions)
292
- - **text-embedding-ada-002**: Legacy 2nd generation model (1,536 dimensions)
293
-
294
- ## TTS Voices
295
-
296
- - **alloy**: Neutral and balanced
297
- - **echo**: Warm and conversational
298
- - **fable**: Expressive and animated
299
- - **onyx**: Deep and authoritative
300
- - **nova**: Friendly and upbeat
301
- - **shimmer**: Soft and gentle
302
-
303
- ## Response Formats
304
-
305
- The OpenAILLM class supports various response formats:
306
-
307
- - `Text`: Regular text responses (default)
308
- - `JSON`: Structured JSON responses (requires compatible model)
309
- - `Markdown`: Markdown-formatted responses
310
- - `Any`: Model decides the format
311
- - `ModelSpecific`: Custom formats with `modelSpecificResponseFormat` parameter
312
-
313
- ## Error Handling
116
+ ## Supported Parameters
314
117
 
315
- The wrapper provides comprehensive error information:
118
+ | Parameter | Supported | Notes |
119
+ |-----------|-----------|-------|
120
+ | temperature | Yes | 0.0 - 2.0 |
121
+ | maxOutputTokens | Yes | Maximum tokens to generate |
122
+ | topP | Yes | Nucleus sampling |
123
+ | frequencyPenalty | Yes | -2.0 to 2.0 |
124
+ | presencePenalty | Yes | -2.0 to 2.0 |
125
+ | seed | Yes | Deterministic outputs |
126
+ | stopSequences | Yes | Custom stop sequences |
127
+ | responseFormat | Yes | JSON, text modes |
128
+ | streaming | Yes | Real-time streaming |
129
+ | effortLevel | Yes | Maps to reasoning_effort |
130
+ | topK | No | Not supported by OpenAI |
131
+ | minP | No | Not supported by OpenAI |
132
+
133
+ ## Extending for Compatible APIs
134
+
135
+ This provider is designed as a base class for any OpenAI-compatible API. To create a new provider, override the base URL:
316
136
 
317
137
  ```typescript
318
- try {
319
- const response = await openAI.ChatCompletion(params);
320
- if (!response.success) {
321
- console.error('Error:', response.errorMessage);
322
- console.error('Status:', response.statusText);
323
- console.error('Time Elapsed:', response.timeElapsed, 'ms');
324
- console.error('Exception:', response.exception);
325
- }
326
- } catch (error) {
327
- console.error('Exception occurred:', error);
138
+ import { OpenAILLM } from '@memberjunction/ai-openai';
139
+ import { RegisterClass } from '@memberjunction/global';
140
+ import { BaseLLM } from '@memberjunction/ai';
141
+
142
+ @RegisterClass(BaseLLM, 'MyProviderLLM')
143
+ export class MyProviderLLM extends OpenAILLM {
144
+ constructor(apiKey: string) {
145
+ super(apiKey);
146
+ // Override the base URL
147
+ this._openai = new OpenAI({
148
+ apiKey: apiKey,
149
+ baseURL: 'https://api.my-provider.com/v1'
150
+ });
151
+ }
328
152
  }
329
153
  ```
330
154
 
331
- ## Integration with MemberJunction
155
+ ## Class Registration
332
156
 
333
- This package seamlessly integrates with the MemberJunction AI framework:
334
-
335
- ```typescript
336
- import { AIEngine } from '@memberjunction/ai';
337
-
338
- // The OpenAI classes are automatically registered
339
- const engine = new AIEngine();
340
- const llm = engine.GetLLM('OpenAILLM', 'your-api-key');
341
- const embeddings = engine.GetEmbedding('OpenAIEmbedding', 'your-api-key');
342
- const tts = engine.GetAudioGenerator('OpenAIAudioGenerator', 'your-api-key');
343
- ```
157
+ - `OpenAILLM` -- Registered via `@RegisterClass(BaseLLM, 'OpenAILLM')`
158
+ - `OpenAIEmbedding` -- Registered via `@RegisterClass(BaseEmbeddings, 'OpenAIEmbedding')`
344
159
 
345
160
  ## Dependencies
346
161
 
347
- - `openai`: Official OpenAI Node.js SDK (v4.98.0)
348
- - `@memberjunction/ai`: MemberJunction AI core framework (v2.43.0)
349
- - `@memberjunction/global`: MemberJunction global utilities (v2.43.0)
350
-
351
- ## Supported Parameters
352
-
353
- The OpenAI provider supports the following LLM parameters:
354
-
355
- **Supported:**
356
- - `temperature` - Controls randomness in the output (0.0-2.0)
357
- - `maxOutputTokens` - Maximum number of tokens to generate
358
- - `topP` - Nucleus sampling threshold (0.0-1.0)
359
- - `frequencyPenalty` - Reduces repetition of token sequences (-2.0 to 2.0)
360
- - `presencePenalty` - Reduces repetition of specific tokens (-2.0 to 2.0)
361
- - `seed` - For deterministic outputs
362
- - `stopSequences` - Array of sequences where the API will stop generating
363
- - `includeLogProbs` - Whether to return log probabilities
364
- - `responseFormat` - Output format (Text, JSON, Markdown, etc.)
365
-
366
- **Not Supported:**
367
- - `topK` - Not available in OpenAI API
368
- - `minP` - Not available in OpenAI API
369
-
370
- ## License
371
-
372
- ISC
162
+ - `@memberjunction/ai` - Core AI abstractions
163
+ - `@memberjunction/global` - Class registration
164
+ - `openai` - Official OpenAI SDK