@memberjunction/ai 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 +242 -0
- package/dist/generic/apiKeyDictionary.d.ts +22 -0
- package/dist/generic/apiKeyDictionary.d.ts.map +1 -1
- package/dist/generic/apiKeyDictionary.js +20 -13
- package/dist/generic/apiKeyDictionary.js.map +1 -1
- package/dist/generic/baseAudio.d.ts +107 -2
- package/dist/generic/baseAudio.d.ts.map +1 -1
- package/dist/generic/baseAudio.js +26 -20
- package/dist/generic/baseAudio.js.map +1 -1
- package/dist/generic/baseDiffusion.d.ts +5 -1
- package/dist/generic/baseDiffusion.d.ts.map +1 -1
- package/dist/generic/baseDiffusion.js +5 -17
- package/dist/generic/baseDiffusion.js.map +1 -1
- package/dist/generic/baseEmbeddings.d.ts +25 -2
- package/dist/generic/baseEmbeddings.d.ts.map +1 -1
- package/dist/generic/baseEmbeddings.js +26 -8
- package/dist/generic/baseEmbeddings.js.map +1 -1
- package/dist/generic/baseImage.d.ts +262 -2
- package/dist/generic/baseImage.d.ts.map +1 -1
- package/dist/generic/baseImage.js +83 -20
- package/dist/generic/baseImage.js.map +1 -1
- package/dist/generic/baseLLM.d.ts +100 -4
- package/dist/generic/baseLLM.d.ts.map +1 -1
- package/dist/generic/baseLLM.js +122 -14
- package/dist/generic/baseLLM.js.map +1 -1
- package/dist/generic/baseModel.d.ts +91 -0
- package/dist/generic/baseModel.d.ts.map +1 -1
- package/dist/generic/baseModel.js +37 -11
- package/dist/generic/baseModel.js.map +1 -1
- package/dist/generic/baseReranker.d.ts +81 -2
- package/dist/generic/baseReranker.d.ts.map +1 -1
- package/dist/generic/baseReranker.js +73 -6
- package/dist/generic/baseReranker.js.map +1 -1
- package/dist/generic/baseVideo.d.ts +24 -1
- package/dist/generic/baseVideo.d.ts.map +1 -1
- package/dist/generic/baseVideo.js +11 -14
- package/dist/generic/baseVideo.js.map +1 -1
- package/dist/generic/chat.types.d.ts +291 -2
- package/dist/generic/chat.types.d.ts.map +1 -1
- package/dist/generic/chat.types.js +105 -32
- package/dist/generic/chat.types.js.map +1 -1
- package/dist/generic/classify.types.d.ts +5 -2
- package/dist/generic/classify.types.d.ts.map +1 -1
- package/dist/generic/classify.types.js +8 -11
- package/dist/generic/classify.types.js.map +1 -1
- package/dist/generic/embed.types.d.ts +1 -1
- package/dist/generic/embed.types.js +1 -2
- package/dist/generic/errorAnalyzer.d.ts +94 -0
- package/dist/generic/errorAnalyzer.d.ts.map +1 -1
- package/dist/generic/errorAnalyzer.js +160 -28
- package/dist/generic/errorAnalyzer.js.map +1 -1
- package/dist/generic/errorTypes.d.ts +116 -0
- package/dist/generic/errorTypes.d.ts.map +1 -1
- package/dist/generic/errorTypes.js +1 -2
- package/dist/generic/reranker.types.d.ts +74 -0
- package/dist/generic/reranker.types.d.ts.map +1 -1
- package/dist/generic/reranker.types.js +10 -2
- package/dist/generic/reranker.types.js.map +1 -1
- package/dist/generic/summarize.types.d.ts +5 -2
- package/dist/generic/summarize.types.d.ts.map +1 -1
- package/dist/generic/summarize.types.js +8 -9
- package/dist/generic/summarize.types.js.map +1 -1
- package/dist/index.d.ts +15 -15
- package/dist/index.js +15 -31
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
- package/readme.md +167 -967
package/readme.md
CHANGED
|
@@ -1,1042 +1,242 @@
|
|
|
1
1
|
# @memberjunction/ai
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Core abstractions and base classes for the MemberJunction AI Framework. This package defines provider-agnostic interfaces for Large Language Models (LLMs), embeddings, image generation, audio, video, reranking, and more. It has **zero MemberJunction dependencies** beyond `@memberjunction/global`, making it suitable for standalone use in any TypeScript/JavaScript project.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Architecture
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TD
|
|
9
|
+
subgraph "@memberjunction/ai"
|
|
10
|
+
BM["BaseModel"]
|
|
11
|
+
style BM fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
BLLM["BaseLLM"]
|
|
14
|
+
style BLLM fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- Base AI model abstractions (`BaseModel`, `BaseLLM`, `BaseEmbeddings`, etc.)
|
|
14
|
-
- Core AI result types (`BaseResult`, `ChatResult`, `ModelUsage`, etc.)
|
|
15
|
-
- Common interfaces and types used across all AI packages
|
|
16
|
-
- **Agent-specific types** have moved to `@memberjunction/ai-agents`
|
|
17
|
-
- **Prompt-specific types** remain in `@memberjunction/ai-prompts`
|
|
18
|
-
- **Engine-specific types** (like agent type definitions) are in `@memberjunction/aiengine`
|
|
16
|
+
BE["BaseEmbeddings"]
|
|
17
|
+
style BE fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
BIG["BaseImageGenerator"]
|
|
20
|
+
style BIG fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
BA["BaseAudio"]
|
|
23
|
+
style BA fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Works in any TypeScript environment that can safely make API calls (e.g. don't use in browsers)
|
|
27
|
-
- Perfect for server-side applications, backend services, and CLI tools
|
|
25
|
+
BV["BaseVideo"]
|
|
26
|
+
style BV fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
BR["BaseReranker"]
|
|
29
|
+
style BR fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
CT["Chat Types"]
|
|
32
|
+
style CT fill:#7c5295,stroke:#563a6b,color:#fff
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- **Base Classes**: Abstract base classes for different AI model types (LLMs, embedding models, audio, video, etc.)
|
|
36
|
-
- **Standard Interfaces**: Consistent interfaces for common AI operations like chat, summarization, and classification
|
|
37
|
-
- **Streaming Support**: Stream responses from supported LLM providers for real-time UIs
|
|
38
|
-
- **Parallel Processing**: Execute multiple chat completions in parallel with progress callbacks
|
|
39
|
-
- **Multi-modal Support**: Handle text, images, videos, audio, and files in chat messages
|
|
40
|
-
- **Type Definitions**: Comprehensive TypeScript type definitions for all AI operations
|
|
41
|
-
- **Error Handling**: Standardized error handling and reporting across all providers
|
|
42
|
-
- **Token Usage Tracking**: Consistent tracking of token usage across providers
|
|
43
|
-
- **Response Format Control**: Specify output formats (Text, Markdown, JSON, or provider-specific)
|
|
44
|
-
- **Additional Settings**: Provider-specific configuration through a flexible settings system
|
|
34
|
+
ET["Embed Types"]
|
|
35
|
+
style ET fill:#7c5295,stroke:#563a6b,color:#fff
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
npm install @memberjunction/ai
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Then install one or more provider packages:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npm install @memberjunction/ai-openai
|
|
56
|
-
npm install @memberjunction/ai-anthropic
|
|
57
|
-
npm install @memberjunction/ai-mistral
|
|
58
|
-
# etc.
|
|
59
|
-
```
|
|
37
|
+
ERR["ErrorAnalyzer"]
|
|
38
|
+
style ERR fill:#b8762f,stroke:#8a5722,color:#fff
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
### Provider-Agnostic Usage (Recommended)
|
|
64
|
-
|
|
65
|
-
For maximum flexibility, use the class factory approach to select the provider at runtime:
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
import { BaseLLM, ChatParams } from '@memberjunction/ai';
|
|
69
|
-
import { MJGlobal } from '@memberjunction/global';
|
|
40
|
+
AK["AIAPIKeys"]
|
|
41
|
+
style AK fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
70
42
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
43
|
+
BM --> BLLM
|
|
44
|
+
BM --> BE
|
|
45
|
+
BM --> BIG
|
|
46
|
+
BM --> BA
|
|
47
|
+
BM --> BV
|
|
48
|
+
BM --> BR
|
|
49
|
+
end
|
|
74
50
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
51
|
+
P1["OpenAI Provider"]
|
|
52
|
+
style P1 fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
53
|
+
P2["Anthropic Provider"]
|
|
54
|
+
style P2 fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
55
|
+
P3["Other Providers"]
|
|
56
|
+
style P3 fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
81
57
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
messages: [
|
|
86
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
87
|
-
{ role: 'user', content: 'What is AI abstraction?' }
|
|
88
|
-
]
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const result = await llm.ChatCompletion(params);
|
|
58
|
+
BLLM --> P1
|
|
59
|
+
BLLM --> P2
|
|
60
|
+
BLLM --> P3
|
|
92
61
|
```
|
|
93
62
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Use environment variables or configuration to select the provider:
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
import { BaseLLM } from '@memberjunction/ai';
|
|
100
|
-
import { MJGlobal } from '@memberjunction/global';
|
|
101
|
-
import dotenv from 'dotenv';
|
|
102
|
-
|
|
103
|
-
// Required to stop tree-shaking of the OpenAILLM - since there's no static code path to this class when using Class Factory pattern, you need this to prevent some bundlers from tree-shaking optimization on this class.
|
|
104
|
-
import { LoadOpenAILLM } from '@memberjunction/ai-openai';
|
|
105
|
-
LoadOpenAILLM();
|
|
106
|
-
|
|
107
|
-
dotenv.config();
|
|
108
|
-
|
|
109
|
-
const providerName = process.env.AI_PROVIDER || 'OpenAILLM';
|
|
110
|
-
const apiKey = process.env.AI_API_KEY;
|
|
63
|
+
## Installation
|
|
111
64
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
providerName,
|
|
115
|
-
apiKey
|
|
116
|
-
);
|
|
65
|
+
```bash
|
|
66
|
+
npm install @memberjunction/ai
|
|
117
67
|
```
|
|
118
68
|
|
|
119
|
-
|
|
69
|
+
## Key Exports
|
|
70
|
+
|
|
71
|
+
### Base Classes
|
|
72
|
+
|
|
73
|
+
| Class | Purpose |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `BaseModel` | Root base class for all AI model types; manages API key storage |
|
|
76
|
+
| `BaseLLM` | Abstract base for chat completion providers with streaming, parallel execution, and thinking model support |
|
|
77
|
+
| `BaseEmbeddings` | Abstract base for text embedding providers |
|
|
78
|
+
| `BaseImageGenerator` | Abstract base for image generation, editing, and variation providers |
|
|
79
|
+
| `BaseAudio` | Abstract base for text-to-speech and speech-to-text providers |
|
|
80
|
+
| `BaseVideo` | Abstract base for video generation providers |
|
|
81
|
+
| `BaseReranker` | Abstract base for document reranking providers |
|
|
82
|
+
|
|
83
|
+
### Type Definitions
|
|
84
|
+
|
|
85
|
+
| Type / Class | Purpose |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `ChatParams` | Parameters for chat completion requests (messages, streaming, sampling controls) |
|
|
88
|
+
| `ChatResult` | Result of a chat completion including choices, usage, and cache info |
|
|
89
|
+
| `ChatMessage` | Individual message with role, content (text or multimodal blocks), and optional metadata |
|
|
90
|
+
| `ChatMessageContentBlock` | Multimodal content block (text, image, video, audio, file) |
|
|
91
|
+
| `StreamingChatCallbacks` | Callbacks for real-time streaming responses |
|
|
92
|
+
| `ParallelChatCompletionsCallbacks` | Callbacks for batch parallel completions |
|
|
93
|
+
| `EmbedTextParams` / `EmbedTextResult` | Parameters and results for single text embedding |
|
|
94
|
+
| `EmbedTextsParams` / `EmbedTextsResult` | Parameters and results for batch text embeddings |
|
|
95
|
+
| `ImageGenerationParams` / `ImageGenerationResult` | Image generation parameters and results |
|
|
96
|
+
| `SummarizeParams` / `SummarizeResult` | Text summarization parameters and results |
|
|
97
|
+
| `ClassifyParams` / `ClassifyResult` | Text classification parameters and results |
|
|
98
|
+
| `RerankParams` / `RerankResult` | Document reranking parameters and results |
|
|
99
|
+
|
|
100
|
+
### Utilities
|
|
101
|
+
|
|
102
|
+
| Export | Purpose |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `BaseResult` | Common result base with success flag, timing, and error info |
|
|
105
|
+
| `ModelUsage` | Token usage and cost tracking (prompt tokens, completion tokens, cost, currency) |
|
|
106
|
+
| `AIAPIKeys` | API key management via environment variables (`AI_VENDOR_API_KEY__<DRIVER>`) |
|
|
107
|
+
| `GetAIAPIKey()` | Helper to resolve API keys with optional runtime overrides |
|
|
108
|
+
| `ErrorAnalyzer` | Standardized error analysis across all providers with severity and failover hints |
|
|
109
|
+
| `AIErrorInfo` / `AIErrorType` | Structured error types (rate limit, authentication, context length, etc.) |
|
|
110
|
+
| `serializeMessageContent()` / `deserializeMessageContent()` | Content block serialization for database storage |
|
|
111
|
+
| `parseBase64DataUrl()` / `createBase64DataUrl()` | Base64 data URL utilities |
|
|
120
112
|
|
|
121
|
-
|
|
113
|
+
## Usage
|
|
114
|
+
|
|
115
|
+
### Basic Chat Completion
|
|
122
116
|
|
|
123
117
|
```typescript
|
|
118
|
+
import { ChatParams, ChatMessageRole } from '@memberjunction/ai';
|
|
124
119
|
import { OpenAILLM } from '@memberjunction/ai-openai';
|
|
125
120
|
|
|
126
|
-
|
|
127
|
-
// Create an instance with your API key
|
|
128
|
-
const llm = new OpenAILLM('your-openai-api-key');
|
|
121
|
+
const llm = new OpenAILLM('your-api-key');
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
{ role: 'user', content: 'What is AI abstraction?' }
|
|
136
|
-
]
|
|
137
|
-
});
|
|
123
|
+
const params = new ChatParams();
|
|
124
|
+
params.model = 'gpt-4';
|
|
125
|
+
params.messages = [
|
|
126
|
+
{ role: ChatMessageRole.user, content: 'What is the capital of France?' }
|
|
127
|
+
];
|
|
138
128
|
|
|
129
|
+
const result = await llm.ChatCompletion(params);
|
|
139
130
|
console.log(result.data.choices[0].message.content);
|
|
140
131
|
```
|
|
141
132
|
|
|
142
|
-
## Core Abstractions
|
|
143
|
-
|
|
144
|
-
### Base Models
|
|
145
|
-
|
|
146
|
-
#### BaseModel
|
|
147
|
-
The foundational abstract class for all AI models. Provides:
|
|
148
|
-
- Protected API key management
|
|
149
|
-
- Base parameter and result types
|
|
150
|
-
- Model usage tracking
|
|
151
|
-
|
|
152
|
-
#### BaseLLM
|
|
153
|
-
Abstract class for text generation models. Features:
|
|
154
|
-
- Standard and streaming chat completions
|
|
155
|
-
- Parallel chat completions with callbacks
|
|
156
|
-
- Text summarization
|
|
157
|
-
- Text classification
|
|
158
|
-
- Additional provider-specific settings management
|
|
159
|
-
- Response format control (Any, Text, Markdown, JSON, ModelSpecific)
|
|
160
|
-
- Support for reasoning budget tokens (for reasoning models)
|
|
161
|
-
- Advanced sampling parameters (see [Parameter Reference](#parameter-reference) below)
|
|
162
|
-
|
|
163
|
-
#### BaseEmbeddings
|
|
164
|
-
Abstract class for text embedding models. Provides:
|
|
165
|
-
- Single text embedding generation
|
|
166
|
-
- Batch text embedding generation
|
|
167
|
-
- Model listing capabilities
|
|
168
|
-
- Additional settings management
|
|
169
|
-
|
|
170
|
-
#### BaseAudioGenerator
|
|
171
|
-
Abstract class for audio processing models. Supports:
|
|
172
|
-
- Text-to-speech generation
|
|
173
|
-
- Speech-to-text transcription
|
|
174
|
-
- Voice listing and management
|
|
175
|
-
- Model and pronunciation dictionary queries
|
|
176
|
-
- Configurable voice settings (stability, similarity, speed, etc.)
|
|
177
|
-
|
|
178
|
-
#### BaseVideoGenerator
|
|
179
|
-
Abstract class for video generation models. Enables:
|
|
180
|
-
- Avatar-based video creation
|
|
181
|
-
- Video translation capabilities
|
|
182
|
-
- Avatar management and listing
|
|
183
|
-
|
|
184
|
-
#### BaseDiffusion
|
|
185
|
-
Abstract class for image generation models (placeholder for future implementation)
|
|
186
|
-
|
|
187
|
-
## LLM Operations
|
|
188
|
-
|
|
189
|
-
### Standard Chat Completion
|
|
190
|
-
|
|
191
|
-
For interactive conversations with AI models:
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
import { ChatParams, ChatResult, ChatMessage } from '@memberjunction/ai';
|
|
195
|
-
|
|
196
|
-
const params: ChatParams = {
|
|
197
|
-
model: 'your-model-name',
|
|
198
|
-
messages: [
|
|
199
|
-
{ role: 'system', content: 'System instruction' },
|
|
200
|
-
{ role: 'user', content: 'User message' },
|
|
201
|
-
{ role: 'assistant', content: 'Assistant response' }
|
|
202
|
-
],
|
|
203
|
-
temperature: 0.7,
|
|
204
|
-
maxOutputTokens: 1000
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const result: ChatResult = await llm.ChatCompletion(params);
|
|
208
|
-
```
|
|
209
|
-
|
|
210
133
|
### Streaming Chat Completion
|
|
211
134
|
|
|
212
|
-
For real-time streaming of responses:
|
|
213
|
-
|
|
214
135
|
```typescript
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
process.stdout.write(chunk);
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
// Called when the complete response is available
|
|
230
|
-
OnComplete: (finalResponse: ChatResult) => {
|
|
231
|
-
console.log("\nFull response:", finalResponse.data.choices[0].message.content);
|
|
232
|
-
console.log("Total tokens:", finalResponse.data.usage.totalTokens);
|
|
233
|
-
},
|
|
234
|
-
|
|
235
|
-
// Called if an error occurs during streaming
|
|
236
|
-
OnError: (error: any) => {
|
|
237
|
-
console.error("Streaming error:", error);
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
// Create streaming chat parameters
|
|
242
|
-
const params: ChatParams = {
|
|
243
|
-
model: 'gpt-4',
|
|
244
|
-
messages: [
|
|
245
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
246
|
-
{ role: 'user', content: 'Write a short poem about AI, one line at a time.' }
|
|
247
|
-
],
|
|
248
|
-
streaming: true, // Enable streaming
|
|
249
|
-
streamingCallbacks: callbacks
|
|
136
|
+
const params = new ChatParams();
|
|
137
|
+
params.model = 'gpt-4';
|
|
138
|
+
params.streaming = true;
|
|
139
|
+
params.messages = [
|
|
140
|
+
{ role: ChatMessageRole.user, content: 'Explain quantum computing' }
|
|
141
|
+
];
|
|
142
|
+
params.streamingCallbacks = {
|
|
143
|
+
OnContent: (chunk, isComplete) => process.stdout.write(chunk),
|
|
144
|
+
OnComplete: (result) => console.log('\nDone!'),
|
|
145
|
+
OnError: (error) => console.error('Stream error:', error)
|
|
250
146
|
};
|
|
251
147
|
|
|
252
|
-
// The ChatCompletion API remains the same, but will stream results
|
|
253
148
|
await llm.ChatCompletion(params);
|
|
254
149
|
```
|
|
255
150
|
|
|
256
|
-
###
|
|
257
|
-
|
|
258
|
-
The MemberJunction AI Core package supports cancellation of long-running operations using the standard JavaScript `AbortSignal` pattern. This provides a clean, standardized way to cancel AI operations when needed.
|
|
259
|
-
|
|
260
|
-
#### Understanding the AbortSignal Pattern
|
|
261
|
-
|
|
262
|
-
The `AbortSignal` pattern uses a **separation of concerns** approach:
|
|
263
|
-
|
|
264
|
-
- **Controller (Caller)**: Creates the `AbortController` and decides **when** to cancel
|
|
265
|
-
- **Worker (AI Operations)**: Receives the `AbortSignal` token and handles **how** to cancel
|
|
266
|
-
|
|
267
|
-
#### Basic Cancellation Example
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
import { ChatParams, BaseLLM } from '@memberjunction/ai';
|
|
271
|
-
|
|
272
|
-
async function cancellableAIChat() {
|
|
273
|
-
// Create the cancellation controller (the "boss")
|
|
274
|
-
const controller = new AbortController();
|
|
275
|
-
|
|
276
|
-
// Set up automatic timeout cancellation
|
|
277
|
-
const timeout = setTimeout(() => {
|
|
278
|
-
controller.abort(); // Cancel after 30 seconds
|
|
279
|
-
}, 30000);
|
|
280
|
-
|
|
281
|
-
try {
|
|
282
|
-
const params: ChatParams = {
|
|
283
|
-
model: 'gpt-4',
|
|
284
|
-
messages: [
|
|
285
|
-
{ role: 'user', content: 'Write a very long story...' }
|
|
286
|
-
],
|
|
287
|
-
cancellationToken: controller.signal // Pass the signal token
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
const result = await llm.ChatCompletion(params);
|
|
291
|
-
clearTimeout(timeout); // Clear timeout if completed successfully
|
|
292
|
-
return result;
|
|
293
|
-
|
|
294
|
-
} catch (error) {
|
|
295
|
-
if (error.message.includes('cancelled')) {
|
|
296
|
-
console.log('Operation was cancelled');
|
|
297
|
-
} else {
|
|
298
|
-
console.error('Operation failed:', error);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
#### User-Initiated Cancellation
|
|
305
|
-
|
|
306
|
-
Perfect for UI applications where users can cancel operations:
|
|
307
|
-
|
|
308
|
-
```typescript
|
|
309
|
-
class AIInterface {
|
|
310
|
-
private currentController: AbortController | null = null;
|
|
311
|
-
|
|
312
|
-
async startAIConversation() {
|
|
313
|
-
// Create new controller for this conversation
|
|
314
|
-
this.currentController = new AbortController();
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
const result = await llm.ChatCompletion({
|
|
318
|
-
model: 'gpt-4',
|
|
319
|
-
messages: [{ role: 'user', content: 'Generate a detailed report...' }],
|
|
320
|
-
cancellationToken: this.currentController.signal
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
console.log('AI Response:', result.data.choices[0].message.content);
|
|
324
|
-
} catch (error) {
|
|
325
|
-
if (error.message.includes('cancelled')) {
|
|
326
|
-
console.log('User cancelled the conversation');
|
|
327
|
-
}
|
|
328
|
-
} finally {
|
|
329
|
-
this.currentController = null;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Called when user clicks "Cancel" button
|
|
334
|
-
cancelConversation() {
|
|
335
|
-
if (this.currentController) {
|
|
336
|
-
this.currentController.abort(); // Instant cancellation
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
#### Multiple Cancellation Sources
|
|
343
|
-
|
|
344
|
-
One signal can be cancelled from multiple sources:
|
|
345
|
-
|
|
346
|
-
```typescript
|
|
347
|
-
async function smartAIExecution() {
|
|
348
|
-
const controller = new AbortController();
|
|
349
|
-
const signal = controller.signal;
|
|
350
|
-
|
|
351
|
-
// 1. User cancel button
|
|
352
|
-
document.getElementById('cancel')?.addEventListener('click', () => {
|
|
353
|
-
controller.abort(); // User cancellation
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
// 2. Resource limit cancellation
|
|
357
|
-
if (await checkMemoryUsage() > MAX_MEMORY) {
|
|
358
|
-
controller.abort(); // Resource limit cancellation
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// 3. Window unload cancellation
|
|
362
|
-
window.addEventListener('beforeunload', () => {
|
|
363
|
-
controller.abort(); // Page closing cancellation
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
// 4. Timeout cancellation
|
|
367
|
-
setTimeout(() => controller.abort(), 60000); // 1 minute timeout
|
|
368
|
-
|
|
369
|
-
try {
|
|
370
|
-
const result = await llm.ChatCompletion({
|
|
371
|
-
model: 'gpt-4',
|
|
372
|
-
messages: [{ role: 'user', content: 'Complex analysis task...' }],
|
|
373
|
-
cancellationToken: signal // One token, many cancel sources!
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
return result;
|
|
377
|
-
} catch (error) {
|
|
378
|
-
// The AI operation doesn't know WHY it was cancelled - just that it should stop
|
|
379
|
-
console.log('AI operation was cancelled:', error.message);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
#### How It Works Internally
|
|
385
|
-
|
|
386
|
-
The AI Core package implements cancellation at multiple levels:
|
|
387
|
-
|
|
388
|
-
1. **BaseLLM Level**: Checks cancellation token before and during operations
|
|
389
|
-
2. **Provider Level**: Native cancellation support where available (e.g., fetch API)
|
|
390
|
-
3. **Fallback Pattern**: Promise.race for providers without native cancellation
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
// Internal implementation example (simplified)
|
|
394
|
-
async ChatCompletion(params: ChatParams): Promise<ChatResult> {
|
|
395
|
-
// Check if already cancelled before starting
|
|
396
|
-
if (params.cancellationToken?.aborted) {
|
|
397
|
-
throw new Error('Operation was cancelled');
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// For providers with native cancellation support
|
|
401
|
-
if (this.hasNativeCancellation) {
|
|
402
|
-
return await this.callProviderAPI({
|
|
403
|
-
...params,
|
|
404
|
-
signal: params.cancellationToken // Native fetch cancellation
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Fallback: Promise.race pattern for other providers
|
|
409
|
-
const promises = [
|
|
410
|
-
this.callProviderAPI(params) // The actual AI call
|
|
411
|
-
];
|
|
412
|
-
|
|
413
|
-
if (params.cancellationToken) {
|
|
414
|
-
promises.push(
|
|
415
|
-
new Promise<never>((_, reject) => {
|
|
416
|
-
params.cancellationToken!.addEventListener('abort', () => {
|
|
417
|
-
reject(new Error('Operation was cancelled'));
|
|
418
|
-
});
|
|
419
|
-
})
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
return await Promise.race(promises);
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
#### Key Benefits
|
|
428
|
-
|
|
429
|
-
1. **🎯 Responsive UX**: Users can cancel long-running AI operations instantly
|
|
430
|
-
2. **💾 Resource Management**: Prevent runaway operations from consuming resources
|
|
431
|
-
3. **🔄 Composable**: Easy to combine user actions, timeouts, and resource limits
|
|
432
|
-
4. **📱 Standard API**: Uses native JavaScript AbortSignal - no custom patterns
|
|
433
|
-
5. **🧹 Clean Cleanup**: Automatic resource cleanup when operations are cancelled
|
|
434
|
-
|
|
435
|
-
The cancellation token pattern provides a **robust, standardized way** to make AI operations responsive and resource-efficient!
|
|
436
|
-
|
|
437
|
-
### Text Summarization
|
|
438
|
-
|
|
439
|
-
For summarizing longer text content:
|
|
440
|
-
|
|
441
|
-
```typescript
|
|
442
|
-
import { SummarizeParams, SummarizeResult } from '@memberjunction/ai';
|
|
443
|
-
|
|
444
|
-
const params: SummarizeParams = {
|
|
445
|
-
text: 'Long text to summarize...',
|
|
446
|
-
model: 'your-model-name',
|
|
447
|
-
maxWords: 100
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
const result: SummarizeResult = await llm.SummarizeText(params);
|
|
451
|
-
console.log(result.summary);
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
### Text Classification
|
|
455
|
-
|
|
456
|
-
For categorizing text into predefined classes:
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
import { ClassifyParams, ClassifyResult } from '@memberjunction/ai';
|
|
460
|
-
|
|
461
|
-
const params: ClassifyParams = {
|
|
462
|
-
text: 'Text to classify',
|
|
463
|
-
model: 'your-model-name',
|
|
464
|
-
classes: ['Category1', 'Category2', 'Category3']
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
const result: ClassifyResult = await llm.ClassifyText(params);
|
|
468
|
-
console.log(result.classification);
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
## Response Format Control
|
|
472
|
-
|
|
473
|
-
Control the format of AI responses:
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
const params: ChatParams = {
|
|
477
|
-
// ...other parameters
|
|
478
|
-
responseFormat: 'JSON', // 'Any', 'Text', 'Markdown', 'JSON', or 'ModelSpecific'
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
// For provider-specific response formats
|
|
482
|
-
const customFormatParams: ChatParams = {
|
|
483
|
-
// ...other parameters
|
|
484
|
-
responseFormat: 'ModelSpecific',
|
|
485
|
-
modelSpecificResponseFormat: {
|
|
486
|
-
// Provider-specific format options
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
## Error Handling
|
|
492
|
-
|
|
493
|
-
### Enhanced Error Information (v2.47.0+)
|
|
494
|
-
|
|
495
|
-
The MemberJunction AI Core package now provides rich, structured error information to enable intelligent retry logic and provider failover. All operations return results extending `BaseResult` which now includes detailed error information.
|
|
496
|
-
|
|
497
|
-
#### Basic Error Handling
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
const result = await llm.ChatCompletion(params);
|
|
501
|
-
|
|
502
|
-
if (!result.success) {
|
|
503
|
-
console.error('Error:', result.errorMessage);
|
|
504
|
-
console.error('Status Text:', result.statusText);
|
|
505
|
-
console.error('Exception:', result.exception);
|
|
506
|
-
console.error('Time Elapsed:', result.timeElapsed, 'ms');
|
|
507
|
-
} else {
|
|
508
|
-
console.log('Success! Response time:', result.timeElapsed, 'ms');
|
|
509
|
-
}
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
#### Advanced Error Handling with Error Info
|
|
513
|
-
|
|
514
|
-
```typescript
|
|
515
|
-
const result = await llm.ChatCompletion(params);
|
|
516
|
-
|
|
517
|
-
if (!result.success && result.errorInfo) {
|
|
518
|
-
const { errorInfo } = result;
|
|
519
|
-
|
|
520
|
-
console.log(`Error Type: ${errorInfo.errorType}`);
|
|
521
|
-
console.log(`HTTP Status: ${errorInfo.httpStatusCode}`);
|
|
522
|
-
console.log(`Severity: ${errorInfo.severity}`);
|
|
523
|
-
console.log(`Can Failover: ${errorInfo.canFailover}`);
|
|
524
|
-
|
|
525
|
-
// Handle based on error type
|
|
526
|
-
switch (errorInfo.errorType) {
|
|
527
|
-
case 'RateLimit':
|
|
528
|
-
// Wait and retry or switch providers
|
|
529
|
-
const delay = errorInfo.suggestedRetryDelaySeconds || 30;
|
|
530
|
-
console.log(`Rate limited. Retry after ${delay} seconds`);
|
|
531
|
-
break;
|
|
532
|
-
|
|
533
|
-
case 'Authentication':
|
|
534
|
-
// Fatal error - check API keys
|
|
535
|
-
console.error('Authentication failed. Check API key configuration.');
|
|
536
|
-
break;
|
|
537
|
-
|
|
538
|
-
case 'ServiceUnavailable':
|
|
539
|
-
// Try another provider
|
|
540
|
-
if (errorInfo.canFailover) {
|
|
541
|
-
console.log('Service unavailable. Switching to backup provider...');
|
|
542
|
-
}
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### Error Types
|
|
549
|
-
|
|
550
|
-
The package categorizes errors into the following types:
|
|
551
|
-
|
|
552
|
-
- **`RateLimit`**: Rate limit exceeded (HTTP 429). Suggests switching providers or waiting
|
|
553
|
-
- **`Authentication`**: Auth failure (HTTP 401/403). Usually indicates invalid API key
|
|
554
|
-
- **`ServiceUnavailable`**: Service down (HTTP 503). Provider temporarily unavailable
|
|
555
|
-
- **`InternalServerError`**: Server error (HTTP 500). Problem on provider's side
|
|
556
|
-
- **`NetworkError`**: Connection issues, timeouts, DNS failures
|
|
557
|
-
- **`InvalidRequest`**: Bad request format (HTTP 400). Problem with request parameters
|
|
558
|
-
- **`ModelError`**: Model-specific issues (not found, overloaded)
|
|
559
|
-
- **`Unknown`**: Unclassified errors
|
|
560
|
-
|
|
561
|
-
### Error Severity Levels
|
|
562
|
-
|
|
563
|
-
Errors are classified by severity to guide retry strategies:
|
|
564
|
-
|
|
565
|
-
- **`Transient`**: Temporary error that may resolve with immediate retry
|
|
566
|
-
- **`Retriable`**: Error requiring waiting or provider switching before retry
|
|
567
|
-
- **`Fatal`**: Permanent error that won't be resolved by retrying
|
|
568
|
-
|
|
569
|
-
### Error Analysis Utility
|
|
570
|
-
|
|
571
|
-
The package includes an `ErrorAnalyzer` utility for providers to use:
|
|
572
|
-
|
|
573
|
-
```typescript
|
|
574
|
-
import { ErrorAnalyzer } from '@memberjunction/ai';
|
|
575
|
-
|
|
576
|
-
try {
|
|
577
|
-
// Provider API call
|
|
578
|
-
} catch (error) {
|
|
579
|
-
const errorInfo = ErrorAnalyzer.analyzeError(error, 'OpenAI');
|
|
580
|
-
// errorInfo now contains structured error details
|
|
581
|
-
}
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
### Implementing Intelligent Failover
|
|
151
|
+
### Parallel Chat Completions
|
|
585
152
|
|
|
586
153
|
```typescript
|
|
587
|
-
|
|
154
|
+
const paramsArray = [
|
|
155
|
+
{ ...baseParams, temperature: 0.3 },
|
|
156
|
+
{ ...baseParams, temperature: 0.7 },
|
|
157
|
+
{ ...baseParams, temperature: 1.0 }
|
|
158
|
+
];
|
|
588
159
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
for (const provider of this.providers) {
|
|
594
|
-
try {
|
|
595
|
-
const result = await provider.llm.ChatCompletion(params);
|
|
596
|
-
|
|
597
|
-
if (result.success) {
|
|
598
|
-
return result;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Check if we should try another provider
|
|
602
|
-
if (result.errorInfo?.canFailover) {
|
|
603
|
-
console.log(`Provider ${provider.name} failed. Trying next...`);
|
|
604
|
-
continue;
|
|
605
|
-
} else {
|
|
606
|
-
// Fatal error - don't try other providers
|
|
607
|
-
return result;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
} catch (error) {
|
|
611
|
-
console.error(`Provider ${provider.name} threw exception:`, error);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
throw new Error('All providers failed');
|
|
616
|
-
}
|
|
617
|
-
}
|
|
160
|
+
const results = await llm.ChatCompletions(paramsArray, {
|
|
161
|
+
OnCompletion: (result, index) => console.log(`Completion ${index} done`),
|
|
162
|
+
OnAllCompleted: (results) => console.log(`All ${results.length} done`)
|
|
163
|
+
});
|
|
618
164
|
```
|
|
619
165
|
|
|
620
|
-
###
|
|
166
|
+
### Multimodal Content
|
|
621
167
|
|
|
622
168
|
```typescript
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
if (lastResult.success) {
|
|
633
|
-
return lastResult;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const errorInfo = lastResult.errorInfo;
|
|
637
|
-
if (!errorInfo || errorInfo.severity === 'Fatal') {
|
|
638
|
-
// Don't retry fatal errors
|
|
639
|
-
return lastResult;
|
|
169
|
+
const params = new ChatParams();
|
|
170
|
+
params.model = 'gpt-4o';
|
|
171
|
+
params.messages = [
|
|
172
|
+
{
|
|
173
|
+
role: ChatMessageRole.user,
|
|
174
|
+
content: [
|
|
175
|
+
{ type: 'text', content: 'What is in this image?' },
|
|
176
|
+
{ type: 'image_url', content: 'data:image/png;base64,...' }
|
|
177
|
+
]
|
|
640
178
|
}
|
|
641
|
-
|
|
642
|
-
// Calculate delay
|
|
643
|
-
const delay = errorInfo.suggestedRetryDelaySeconds ||
|
|
644
|
-
Math.pow(2, attempt - 1) * 1000; // Exponential backoff
|
|
645
|
-
|
|
646
|
-
console.log(`Retry ${attempt}/${maxRetries} after ${delay}s...`);
|
|
647
|
-
await new Promise(resolve => setTimeout(resolve, delay * 1000));
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
return lastResult!;
|
|
651
|
-
}
|
|
652
|
-
```
|
|
653
|
-
|
|
654
|
-
## Token Usage Tracking
|
|
655
|
-
|
|
656
|
-
Monitor token usage consistently across different providers:
|
|
657
|
-
|
|
658
|
-
```typescript
|
|
659
|
-
const result = await llm.ChatCompletion(params);
|
|
660
|
-
console.log('Prompt Tokens:', result.data.usage.promptTokens);
|
|
661
|
-
console.log('Completion Tokens:', result.data.usage.completionTokens);
|
|
662
|
-
console.log('Total Tokens:', result.data.usage.totalTokens);
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
## Available Providers
|
|
666
|
-
|
|
667
|
-
The following provider packages implement the MemberJunction AI abstractions:
|
|
668
|
-
|
|
669
|
-
- [`@memberjunction/ai-openai`](../Providers/OpenAI/readme.md) - OpenAI (GPT models)
|
|
670
|
-
- [`@memberjunction/ai-anthropic`](../Providers/Anthropic/readme.md) - Anthropic (Claude models)
|
|
671
|
-
- [`@memberjunction/ai-mistral`](../Providers/Mistral/readme.md) - Mistral AI
|
|
672
|
-
- [`@memberjunction/ai-gemini`](../Providers/Gemini/readme.md) - Google's Gemini models
|
|
673
|
-
- [`@memberjunction/ai-vertex`](../Providers/Vertex/readme.md) - Google Vertex AI (various models including Gemini, others)
|
|
674
|
-
- [`@memberjunction/ai-bedrock`](../Providers/Bedrock/readme.md) - Amazon Bedrock (Claude, Llama, Titan, etc.)
|
|
675
|
-
- [`@memberjunction/ai-groq`](../Providers/Groq/readme.md) - Groq's optimized inference (https://www.groq.com)
|
|
676
|
-
- [`@memberjunction/ai-bettybot`](../Providers/BettyBot/readme.md) - Betty AI (https://www.meetbetty.ai)
|
|
677
|
-
- [`@memberjunction/ai-azure`](../Providers/Azure/readme.md) - Azure AI Foundry with support for OpenAI, Mistral, Phi, more
|
|
678
|
-
- [`@memberjunction/ai-cerebras`](../Providers/Cerebras/readme.md) - Cerebras models
|
|
679
|
-
- [`@memberjunction/ai-elevenlabs`](../Providers/ElevenLabs/readme.md) - ElevenLabs audio models
|
|
680
|
-
- [`@memberjunction/ai-heygen`](../Providers/HeyGen/readme.md) - HeyGen video models
|
|
681
|
-
|
|
682
|
-
Note: Each provider implements the features they support. See individual provider documentation for specific capabilities.
|
|
683
|
-
|
|
684
|
-
## Implementation Details
|
|
685
|
-
|
|
686
|
-
### Streaming Architecture
|
|
687
|
-
|
|
688
|
-
The BaseLLM class uses a template method pattern for handling streaming:
|
|
689
|
-
|
|
690
|
-
1. The main `ChatCompletion` method checks if streaming is requested and supported
|
|
691
|
-
2. If streaming is enabled, it calls the template method `handleStreamingChatCompletion`
|
|
692
|
-
3. Provider implementations supply three key methods:
|
|
693
|
-
- `createStreamingRequest`: Creates the provider-specific streaming request
|
|
694
|
-
- `processStreamingChunk`: Processes individual chunks from the stream
|
|
695
|
-
- `finalizeStreamingResponse`: Creates the final response object
|
|
696
|
-
|
|
697
|
-
This architecture allows for a clean separation between common streaming logic and provider-specific implementations.
|
|
698
|
-
|
|
699
|
-
## Import Examples
|
|
700
|
-
|
|
701
|
-
```typescript
|
|
702
|
-
// Import base model classes
|
|
703
|
-
import { BaseLLM, BaseEmbeddings, BaseAudioGenerator } from '@memberjunction/ai';
|
|
704
|
-
|
|
705
|
-
// Import result types
|
|
706
|
-
import { ChatResult, ModelUsage, BaseResult } from '@memberjunction/ai';
|
|
707
|
-
|
|
708
|
-
// Import parameter types
|
|
709
|
-
import { ChatParams, ChatMessage, StreamingChatCallbacks } from '@memberjunction/ai';
|
|
710
|
-
|
|
711
|
-
// Import utility classes
|
|
712
|
-
import { AIAPIKeys, GetAIAPIKey } from '@memberjunction/ai';
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
## Dependencies
|
|
716
|
-
|
|
717
|
-
- `@memberjunction/global` - MemberJunction global utilities including class factory
|
|
718
|
-
- `rxjs` - Reactive extensions for JavaScript
|
|
719
|
-
|
|
720
|
-
## Type Exports
|
|
721
|
-
|
|
722
|
-
The Core package exports fundamental types used throughout the AI ecosystem:
|
|
723
|
-
|
|
724
|
-
### Base Model Classes
|
|
725
|
-
- `BaseModel` - Foundation class for all AI models
|
|
726
|
-
- `BaseLLM` - Base class for language models
|
|
727
|
-
- `BaseEmbeddings` - Base class for embedding models
|
|
728
|
-
- `BaseAudioGenerator` - Base class for audio models
|
|
729
|
-
- `BaseVideoGenerator` - Base class for video models
|
|
730
|
-
- `BaseDiffusion` - Base class for image generation models
|
|
731
|
-
|
|
732
|
-
### Core Result Types
|
|
733
|
-
- `BaseResult` - Base result structure for all AI operations
|
|
734
|
-
- `ChatResult` - Result from chat completions
|
|
735
|
-
- `ModelUsage` - Token/resource usage tracking
|
|
736
|
-
- `SummarizeResult` - Text summarization results
|
|
737
|
-
- `ClassifyResult` - Text classification results
|
|
738
|
-
- `EmbeddingResult` - Embedding generation results
|
|
739
|
-
|
|
740
|
-
### Common Interfaces
|
|
741
|
-
- `ChatMessage` - Message structure for conversations
|
|
742
|
-
- `ChatParams` - Parameters for chat operations
|
|
743
|
-
- `StreamingChatCallbacks` - Callbacks for streaming responses
|
|
744
|
-
- `ParallelChatCompletionsCallbacks` - Callbacks for parallel execution
|
|
745
|
-
|
|
746
|
-
## API Reference
|
|
747
|
-
|
|
748
|
-
### Result Types
|
|
749
|
-
|
|
750
|
-
#### BaseResult
|
|
751
|
-
All operations return results extending `BaseResult`:
|
|
752
|
-
```typescript
|
|
753
|
-
class BaseResult {
|
|
754
|
-
success: boolean;
|
|
755
|
-
startTime: Date;
|
|
756
|
-
endTime: Date;
|
|
757
|
-
errorMessage: string;
|
|
758
|
-
exception: any;
|
|
759
|
-
errorInfo?: AIErrorInfo; // Enhanced error details (v2.47.0+)
|
|
760
|
-
timeElapsed: number; // Computed getter
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
// Enhanced error information structure
|
|
764
|
-
interface AIErrorInfo {
|
|
765
|
-
httpStatusCode?: number; // HTTP status code (429, 500, etc.)
|
|
766
|
-
errorType: AIErrorType; // Categorized error type
|
|
767
|
-
severity: ErrorSeverity; // Transient, Retriable, or Fatal
|
|
768
|
-
suggestedRetryDelaySeconds?: number; // Provider-suggested retry delay
|
|
769
|
-
canFailover: boolean; // Whether switching providers might help
|
|
770
|
-
providerErrorCode?: string; // Original provider error code
|
|
771
|
-
context?: Record<string, any>; // Additional error context
|
|
772
|
-
}
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
#### ChatResult
|
|
776
|
-
Extends `BaseResult` with chat-specific data:
|
|
777
|
-
```typescript
|
|
778
|
-
class ChatResult extends BaseResult {
|
|
779
|
-
data: {
|
|
780
|
-
choices: Array<{
|
|
781
|
-
message: ChatCompletionMessage;
|
|
782
|
-
index: number;
|
|
783
|
-
finishReason?: string;
|
|
784
|
-
}>;
|
|
785
|
-
usage: ModelUsage;
|
|
786
|
-
};
|
|
787
|
-
statusText?: string;
|
|
788
|
-
}
|
|
789
|
-
```
|
|
790
|
-
|
|
791
|
-
### Chat Message Types
|
|
792
|
-
|
|
793
|
-
#### ChatMessage
|
|
794
|
-
Supports multi-modal content and optional typed metadata:
|
|
795
|
-
```typescript
|
|
796
|
-
type ChatMessage<M = any> = {
|
|
797
|
-
role: 'system' | 'user' | 'assistant';
|
|
798
|
-
content: string | ChatMessageContentBlock[];
|
|
799
|
-
metadata?: M; // Optional typed metadata for extended functionality
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
type ChatMessageContentBlock = {
|
|
803
|
-
type: 'text' | 'image_url' | 'video_url' | 'audio_url' | 'file_url';
|
|
804
|
-
content: string; // URL or base64 encoded content
|
|
805
|
-
}
|
|
179
|
+
];
|
|
806
180
|
```
|
|
807
181
|
|
|
808
|
-
|
|
809
|
-
The `ChatMessage` type is now generic, allowing you to attach typed metadata to messages:
|
|
810
|
-
- The generic parameter defaults to `any` for backward compatibility
|
|
811
|
-
- Use `ChatMessage<MyMetadata>` to specify a custom metadata type
|
|
812
|
-
- This enables framework extensions (like agents) to add lifecycle metadata without modifying the core type
|
|
813
|
-
- Example: Agents use `ChatMessage<AgentChatMessageMetadata>` to track message expiration, compaction, and expansion state
|
|
814
|
-
|
|
815
|
-
### Streaming Callbacks
|
|
182
|
+
### Text Embeddings
|
|
816
183
|
|
|
817
184
|
```typescript
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
OnComplete?: (finalResponse: ChatResult) => void;
|
|
821
|
-
OnError?: (error: any) => void;
|
|
822
|
-
}
|
|
185
|
+
import { EmbedTextParams } from '@memberjunction/ai';
|
|
186
|
+
import { OpenAIEmbeddings } from '@memberjunction/ai-openai';
|
|
823
187
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
188
|
+
const embedder = new OpenAIEmbeddings('your-api-key');
|
|
189
|
+
const result = await embedder.EmbedText({
|
|
190
|
+
model: 'text-embedding-ada-002',
|
|
191
|
+
text: 'Sample text to embed'
|
|
192
|
+
});
|
|
193
|
+
console.log(result.embedding); // number[]
|
|
829
194
|
```
|
|
830
195
|
|
|
831
|
-
## Configuration
|
|
832
|
-
|
|
833
196
|
### API Key Management
|
|
834
197
|
|
|
835
|
-
The package includes a flexible API key management system through the `AIAPIKeys` class:
|
|
836
|
-
|
|
837
198
|
```typescript
|
|
838
199
|
import { GetAIAPIKey } from '@memberjunction/ai';
|
|
839
200
|
|
|
840
|
-
//
|
|
841
|
-
const
|
|
842
|
-
```
|
|
843
|
-
|
|
844
|
-
By default, it looks for environment variables with the pattern: `AI_VENDOR_API_KEY__[PROVIDER_NAME]`
|
|
201
|
+
// Reads from environment: AI_VENDOR_API_KEY__OPENAILLM
|
|
202
|
+
const key = GetAIAPIKey('OpenAILLM');
|
|
845
203
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
AI_VENDOR_API_KEY__MISTRAL=your-api-key
|
|
204
|
+
// With runtime override
|
|
205
|
+
const key2 = GetAIAPIKey('AnthropicLLM', [
|
|
206
|
+
{ driverClass: 'AnthropicLLM', apiKey: 'sk-ant-...' }
|
|
207
|
+
]);
|
|
851
208
|
```
|
|
852
209
|
|
|
853
|
-
|
|
854
|
-
> - Credential resolution hierarchy (vendor → model → prompt → request)
|
|
855
|
-
> - Integration with the encrypted Credentials system
|
|
856
|
-
> - Support for complex authentication schemes (Azure, AWS, OAuth)
|
|
857
|
-
> - Migration path from environment variables
|
|
858
|
-
|
|
859
|
-
#### Custom API Key Management
|
|
210
|
+
## Provider Implementation
|
|
860
211
|
|
|
861
|
-
|
|
212
|
+
To create a new AI provider, extend the appropriate base class:
|
|
862
213
|
|
|
863
214
|
```typescript
|
|
864
|
-
import {
|
|
865
|
-
|
|
866
|
-
@RegisterClass(AIAPIKeys, 'CustomAPIKeys', 2) // Priority 2 overrides default
|
|
867
|
-
export class CustomAPIKeys extends AIAPIKeys {
|
|
868
|
-
public GetAPIKey(AIDriverName: string): string {
|
|
869
|
-
// Your custom logic here
|
|
870
|
-
// Could retrieve from database, vault, etc.
|
|
871
|
-
return super.GetAPIKey(AIDriverName); // Fallback to default
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
```
|
|
875
|
-
|
|
876
|
-
#### Runtime API Key Override
|
|
877
|
-
|
|
878
|
-
As of v2.50.0, you can provide API keys at runtime without modifying environment variables or global configuration. This is useful for multi-tenant applications or testing with different API keys.
|
|
879
|
-
|
|
880
|
-
##### Direct Constructor Usage
|
|
215
|
+
import { BaseLLM, ChatParams, ChatResult } from '@memberjunction/ai';
|
|
881
216
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const llm = new OpenAILLM('sk-your-runtime-api-key');
|
|
888
|
-
```
|
|
889
|
-
|
|
890
|
-
##### With Class Factory Pattern
|
|
891
|
-
|
|
892
|
-
When using the class factory pattern, the API key is passed as the second parameter:
|
|
893
|
-
|
|
894
|
-
```typescript
|
|
895
|
-
import { BaseLLM } from '@memberjunction/ai';
|
|
896
|
-
import { MJGlobal } from '@memberjunction/global';
|
|
897
|
-
|
|
898
|
-
const llm = MJGlobal.Instance.ClassFactory.CreateInstance<BaseLLM>(
|
|
899
|
-
BaseLLM,
|
|
900
|
-
'OpenAILLM',
|
|
901
|
-
'sk-your-runtime-api-key' // Runtime API key
|
|
902
|
-
);
|
|
903
|
-
```
|
|
217
|
+
export class MyProviderLLM extends BaseLLM {
|
|
218
|
+
protected async nonStreamingChatCompletion(params: ChatParams): Promise<ChatResult> {
|
|
219
|
+
// Implement provider-specific chat completion
|
|
220
|
+
}
|
|
904
221
|
|
|
905
|
-
|
|
222
|
+
public async ClassifyText(params: ClassifyParams): Promise<ClassifyResult> {
|
|
223
|
+
// Implement or throw if not supported
|
|
224
|
+
}
|
|
906
225
|
|
|
907
|
-
|
|
226
|
+
public async SummarizeText(params: SummarizeParams): Promise<SummarizeResult> {
|
|
227
|
+
// Implement or throw if not supported
|
|
228
|
+
}
|
|
908
229
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
*/
|
|
915
|
-
driverClass: string;
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* The API key value for the specified driver class
|
|
919
|
-
*/
|
|
920
|
-
apiKey: string;
|
|
230
|
+
// For streaming support, override these:
|
|
231
|
+
public get SupportsStreaming(): boolean { return true; }
|
|
232
|
+
protected async createStreamingRequest(params: ChatParams): Promise<AsyncIterable<unknown>> { /* ... */ }
|
|
233
|
+
protected processStreamingChunk(chunk: unknown): { content: string } { /* ... */ }
|
|
234
|
+
protected finalizeStreamingResponse(content: string, lastChunk: unknown, usage: unknown): ChatResult { /* ... */ }
|
|
921
235
|
}
|
|
922
236
|
```
|
|
923
237
|
|
|
924
|
-
### Provider-Specific Settings
|
|
925
|
-
|
|
926
|
-
Many providers support additional configuration beyond the API key:
|
|
927
|
-
|
|
928
|
-
```typescript
|
|
929
|
-
const llm = new SomeLLM('api-key');
|
|
930
|
-
llm.SetAdditionalSettings({
|
|
931
|
-
baseURL: 'https://custom-endpoint.com',
|
|
932
|
-
organization: 'my-org',
|
|
933
|
-
// Provider-specific settings
|
|
934
|
-
});
|
|
935
|
-
```
|
|
936
|
-
|
|
937
|
-
## Integration with MemberJunction
|
|
938
|
-
|
|
939
|
-
While this package can be used standalone, it integrates seamlessly with the MemberJunction framework:
|
|
940
|
-
|
|
941
|
-
- Uses `@memberjunction/global` for class factory pattern and registration
|
|
942
|
-
- Compatible with MemberJunction's metadata system
|
|
943
|
-
- Can leverage MemberJunction's configuration management when available
|
|
944
|
-
|
|
945
238
|
## Dependencies
|
|
946
239
|
|
|
947
|
-
- `@memberjunction/global`
|
|
948
|
-
- `
|
|
949
|
-
- `
|
|
950
|
-
- `typeorm` (^0.3.20) - ORM functionality (optional, only if using with full MemberJunction)
|
|
951
|
-
|
|
952
|
-
## Development
|
|
953
|
-
|
|
954
|
-
### Building
|
|
955
|
-
|
|
956
|
-
```bash
|
|
957
|
-
cd packages/AI/Core
|
|
958
|
-
npm run build
|
|
959
|
-
```
|
|
960
|
-
|
|
961
|
-
### TypeScript Configuration
|
|
962
|
-
|
|
963
|
-
The package is configured with TypeScript strict mode and targets ES2022. See `tsconfig.json` for full compiler options.
|
|
964
|
-
|
|
965
|
-
## Best Practices
|
|
966
|
-
|
|
967
|
-
1. **Always use the class factory pattern** for maximum flexibility
|
|
968
|
-
2. **Handle errors gracefully** - check `result.success` before accessing data
|
|
969
|
-
3. **Monitor token usage** to manage costs and stay within limits
|
|
970
|
-
4. **Use streaming for long responses** to improve user experience
|
|
971
|
-
5. **Leverage parallel completions** for comparison or reliability
|
|
972
|
-
6. **Cache API keys** using the built-in caching mechanism
|
|
973
|
-
7. **Specify response formats** when you need structured output
|
|
974
|
-
|
|
975
|
-
## Troubleshooting
|
|
976
|
-
|
|
977
|
-
### Common Issues
|
|
978
|
-
|
|
979
|
-
1. **"API key cannot be empty" error**
|
|
980
|
-
- Ensure you're passing a valid API key to the constructor
|
|
981
|
-
- Check environment variables are properly set
|
|
982
|
-
|
|
983
|
-
2. **Provider not found when using class factory**
|
|
984
|
-
- Make sure to import and call the provider's Load function
|
|
985
|
-
- Verify the provider class name matches exactly
|
|
986
|
-
|
|
987
|
-
3. **Streaming not working**
|
|
988
|
-
- Check if the provider supports streaming (`llm.SupportsStreaming`)
|
|
989
|
-
- Ensure streaming callbacks are properly defined
|
|
990
|
-
|
|
991
|
-
4. **Type errors with content blocks**
|
|
992
|
-
- Use the provided type guards and interfaces
|
|
993
|
-
- Ensure content format matches the expected structure
|
|
994
|
-
|
|
995
|
-
## Parameter Reference
|
|
996
|
-
|
|
997
|
-
### ChatParams Parameters
|
|
998
|
-
|
|
999
|
-
The `ChatParams` class supports the following parameters for controlling LLM behavior:
|
|
1000
|
-
|
|
1001
|
-
#### Core Parameters (from BaseParams)
|
|
1002
|
-
- `model` (required): The model name to use
|
|
1003
|
-
- `temperature`: Controls randomness (0.0 = deterministic, 2.0 = very random)
|
|
1004
|
-
- `maxOutputTokens`: Maximum tokens to generate in response
|
|
1005
|
-
- `responseFormat`: Output format - 'Any', 'Text', 'Markdown', 'JSON', or 'ModelSpecific'
|
|
1006
|
-
- `seed`: Random seed for reproducible outputs (provider-dependent)
|
|
1007
|
-
- `stopSequences`: Array of sequences that will stop generation
|
|
1008
|
-
|
|
1009
|
-
#### Sampling Parameters
|
|
1010
|
-
- `topP`: Top-p (nucleus) sampling (0-1). Alternative to temperature, considers cumulative probability
|
|
1011
|
-
- `topK`: Top-k sampling. Limits to top K most likely tokens (provider-dependent)
|
|
1012
|
-
- `minP`: Minimum probability threshold (0-1). Filters out low-probability tokens
|
|
1013
|
-
|
|
1014
|
-
#### Repetition Control
|
|
1015
|
-
- `frequencyPenalty`: Reduce token repetition based on frequency (-2.0 to 2.0)
|
|
1016
|
-
- `presencePenalty`: Encourage topic diversity (-2.0 to 2.0)
|
|
1017
|
-
|
|
1018
|
-
#### Advanced Features
|
|
1019
|
-
- `streaming`: Enable streaming responses
|
|
1020
|
-
- `includeLogProbs`: Request log probabilities for tokens
|
|
1021
|
-
- `topLogProbs`: Number of top log probabilities to return (2-20)
|
|
1022
|
-
- `effortLevel`: Model-specific effort/reasoning level
|
|
1023
|
-
- `reasoningBudgetTokens`: Token budget for reasoning models
|
|
1024
|
-
- `enableCaching`: Enable provider caching features
|
|
1025
|
-
- `cancellationToken`: AbortSignal for cancelling operations
|
|
1026
|
-
|
|
1027
|
-
### Provider Support
|
|
1028
|
-
|
|
1029
|
-
Not all providers support all parameters. The framework will:
|
|
1030
|
-
- Pass supported parameters to the provider
|
|
1031
|
-
- Log warnings for unsupported parameters (visible in console)
|
|
1032
|
-
- Continue execution without failing
|
|
1033
|
-
|
|
1034
|
-
Common support patterns:
|
|
1035
|
-
- **OpenAI**: Supports most parameters except topK, minP
|
|
1036
|
-
- **Anthropic**: Supports topP, topK, but not frequency/presence penalties
|
|
1037
|
-
- **Google/Gemini**: Supports topP, topK, temperature
|
|
1038
|
-
- **Others**: Vary by provider - check console warnings
|
|
1039
|
-
|
|
1040
|
-
## License
|
|
1041
|
-
|
|
1042
|
-
See the [repository root](../../../LICENSE) for license information.
|
|
240
|
+
- `@memberjunction/global` -- Class factory and global utilities (zero transitive dependencies)
|
|
241
|
+
- `dotenv` -- Environment variable loading
|
|
242
|
+
- `rxjs` -- Reactive extensions (used internally)
|