@bernierllc/ai-provider-openai 1.0.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/.eslintrc.js +35 -0
- package/README.md +294 -0
- package/__tests__/OpenAIProvider.test.ts +574 -0
- package/__tests__/error-handling.test.ts +315 -0
- package/__tests__/model-registry.test.ts +270 -0
- package/__tests__/openai-specific.test.ts +333 -0
- package/dist/OpenAIProvider.d.ts +22 -0
- package/dist/OpenAIProvider.d.ts.map +1 -0
- package/dist/OpenAIProvider.js +320 -0
- package/dist/OpenAIProvider.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/models/model-registry.d.ts +8 -0
- package/dist/models/model-registry.d.ts.map +1 -0
- package/dist/models/model-registry.js +147 -0
- package/dist/models/model-registry.js.map +1 -0
- package/dist/types/openai-types.d.ts +28 -0
- package/dist/types/openai-types.d.ts.map +1 -0
- package/dist/types/openai-types.js +3 -0
- package/dist/types/openai-types.js.map +1 -0
- package/dist/utils/error-handling.d.ts +5 -0
- package/dist/utils/error-handling.d.ts.map +1 -0
- package/dist/utils/error-handling.js +67 -0
- package/dist/utils/error-handling.js.map +1 -0
- package/jest.config.cjs +29 -0
- package/package.json +63 -0
- package/src/OpenAIProvider.ts +435 -0
- package/src/index.ts +12 -0
- package/src/models/model-registry.ts +178 -0
- package/src/types/openai-types.ts +51 -0
- package/src/utils/error-handling.ts +101 -0
- package/tsconfig.json +31 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Bernier LLC
|
|
3
|
+
|
|
4
|
+
This file is licensed to the client under a limited-use license.
|
|
5
|
+
The client may use and modify this code only within the scope of the project it was delivered for.
|
|
6
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
parser: '@typescript-eslint/parser',
|
|
11
|
+
extends: [
|
|
12
|
+
'eslint:recommended',
|
|
13
|
+
'plugin:@typescript-eslint/recommended',
|
|
14
|
+
'plugin:@typescript-eslint/recommended-requiring-type-checking'
|
|
15
|
+
],
|
|
16
|
+
parserOptions: {
|
|
17
|
+
ecmaVersion: 2020,
|
|
18
|
+
sourceType: 'module',
|
|
19
|
+
project: './tsconfig.json',
|
|
20
|
+
tsconfigRootDir: __dirname
|
|
21
|
+
},
|
|
22
|
+
rules: {
|
|
23
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
24
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
25
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
26
|
+
'@typescript-eslint/no-unused-vars': ['error', {
|
|
27
|
+
argsIgnorePattern: '^_',
|
|
28
|
+
varsIgnorePattern: '^_'
|
|
29
|
+
}]
|
|
30
|
+
},
|
|
31
|
+
env: {
|
|
32
|
+
node: true,
|
|
33
|
+
jest: true
|
|
34
|
+
}
|
|
35
|
+
};
|
package/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# @bernierllc/ai-provider-openai
|
|
2
|
+
|
|
3
|
+
OpenAI API adapter implementing the unified AI provider interface for seamless integration across BernierLLC projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bernierllc/ai-provider-openai
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @bernierllc/ai-provider-openai
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Complete OpenAI API Support**: GPT-4, GPT-3.5, embeddings, moderation, vision
|
|
16
|
+
- **Streaming Completions**: Real-time text generation with async generators
|
|
17
|
+
- **Function Calling**: Support for OpenAI function calling capabilities
|
|
18
|
+
- **Vision Analysis**: GPT-4 Vision for image understanding
|
|
19
|
+
- **Cost Estimation**: Accurate token and cost estimation before requests
|
|
20
|
+
- **Type Safety**: Full TypeScript support with strict typing
|
|
21
|
+
- **Error Handling**: Comprehensive error handling with retry logic
|
|
22
|
+
- **Health Monitoring**: API health checks and availability detection
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Basic Completion
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { OpenAIProvider } from '@bernierllc/ai-provider-openai';
|
|
30
|
+
|
|
31
|
+
const provider = new OpenAIProvider({
|
|
32
|
+
providerName: 'openai',
|
|
33
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
34
|
+
defaultModel: 'gpt-4-turbo',
|
|
35
|
+
timeout: 30000,
|
|
36
|
+
maxRetries: 3
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Generate completion
|
|
40
|
+
const response = await provider.complete({
|
|
41
|
+
messages: [
|
|
42
|
+
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
43
|
+
{ role: 'user', content: 'Explain TypeScript generics in simple terms.' }
|
|
44
|
+
],
|
|
45
|
+
maxTokens: 500,
|
|
46
|
+
temperature: 0.7
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (response.success) {
|
|
50
|
+
console.log(response.content);
|
|
51
|
+
console.log(`Tokens used: ${response.usage?.totalTokens}`);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Streaming Completion
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
console.log('Generating response...\n');
|
|
59
|
+
|
|
60
|
+
for await (const chunk of provider.streamComplete({
|
|
61
|
+
messages: [
|
|
62
|
+
{ role: 'user', content: 'Write a short poem about coding' }
|
|
63
|
+
]
|
|
64
|
+
})) {
|
|
65
|
+
process.stdout.write(chunk.delta);
|
|
66
|
+
|
|
67
|
+
if (chunk.finishReason) {
|
|
68
|
+
console.log(`\n\nFinished: ${chunk.finishReason}`);
|
|
69
|
+
if (chunk.usage) {
|
|
70
|
+
console.log(`Tokens: ${chunk.usage.totalTokens}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Function Calling
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const response = await provider.completionWithFunctions({
|
|
80
|
+
messages: [
|
|
81
|
+
{ role: 'user', content: 'What is the weather in San Francisco?' }
|
|
82
|
+
],
|
|
83
|
+
functions: [
|
|
84
|
+
{
|
|
85
|
+
name: 'get_weather',
|
|
86
|
+
description: 'Get the current weather for a location',
|
|
87
|
+
parameters: {
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties: {
|
|
90
|
+
location: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description: 'The city and state, e.g. San Francisco, CA'
|
|
93
|
+
},
|
|
94
|
+
unit: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
enum: ['celsius', 'fahrenheit']
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
required: ['location']
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (response.metadata?.functionCall) {
|
|
106
|
+
console.log('Function call:', response.metadata.functionCall);
|
|
107
|
+
// { name: 'get_weather', arguments: '{"location":"San Francisco, CA"}' }
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Vision Analysis
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const analysis = await provider.analyzeImage(
|
|
115
|
+
'https://example.com/image.jpg',
|
|
116
|
+
'What objects do you see in this image?',
|
|
117
|
+
'gpt-4-vision-preview'
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (analysis.success) {
|
|
121
|
+
console.log(analysis.content);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Embeddings
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const embeddings = await provider.generateEmbeddings({
|
|
129
|
+
input: [
|
|
130
|
+
'TypeScript is a typed superset of JavaScript',
|
|
131
|
+
'Python is a high-level programming language'
|
|
132
|
+
],
|
|
133
|
+
model: 'text-embedding-3-small'
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (embeddings.success) {
|
|
137
|
+
console.log(`Generated ${embeddings.embeddings?.length} embeddings`);
|
|
138
|
+
console.log(`Dimensions: ${embeddings.embeddings?.[0].length}`);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Content Moderation
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const moderation = await provider.moderate(
|
|
146
|
+
'Some content to check for policy violations'
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
if (moderation.success) {
|
|
150
|
+
console.log(`Flagged: ${moderation.flagged}`);
|
|
151
|
+
if (moderation.flagged) {
|
|
152
|
+
console.log('Violated categories:', moderation.categories);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Cost Estimation
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const request = {
|
|
161
|
+
messages: [
|
|
162
|
+
{ role: 'user', content: 'Write a detailed article about TypeScript' }
|
|
163
|
+
],
|
|
164
|
+
maxTokens: 2000
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const cost = provider.estimateCost(request);
|
|
168
|
+
console.log(`Estimated cost: $${cost.estimatedCostUSD.toFixed(4)}`);
|
|
169
|
+
console.log(`Input tokens: ${cost.inputTokens}`);
|
|
170
|
+
console.log(`Output tokens: ${cost.outputTokens}`);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## API
|
|
174
|
+
|
|
175
|
+
### Constructor
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
new OpenAIProvider(config: OpenAIProviderConfig)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Configuration options:
|
|
182
|
+
|
|
183
|
+
- `providerName`: Must be `'openai'`
|
|
184
|
+
- `apiKey`: OpenAI API key (required)
|
|
185
|
+
- `defaultModel`: Default model to use (optional, defaults to 'gpt-4-turbo')
|
|
186
|
+
- `organizationId`: OpenAI organization ID (optional)
|
|
187
|
+
- `baseURL`: Custom API base URL (optional)
|
|
188
|
+
- `timeout`: Request timeout in milliseconds (optional, default: 60000)
|
|
189
|
+
- `maxRetries`: Maximum retry attempts (optional, default: 3)
|
|
190
|
+
|
|
191
|
+
### Methods
|
|
192
|
+
|
|
193
|
+
#### Core Methods (Implements AIProvider interface)
|
|
194
|
+
|
|
195
|
+
- `complete(request: CompletionRequest): Promise<CompletionResponse>` - Generate text completion
|
|
196
|
+
- `streamComplete(request: CompletionRequest): AsyncGenerator<StreamChunk>` - Stream completion chunks
|
|
197
|
+
- `generateEmbeddings(request: EmbeddingRequest): Promise<EmbeddingResponse>` - Generate embeddings
|
|
198
|
+
- `moderate(content: string): Promise<ModerationResponse>` - Check content moderation
|
|
199
|
+
- `getAvailableModels(): Promise<ModelInfo[]>` - List available models
|
|
200
|
+
- `checkHealth(): Promise<HealthStatus>` - Check API health
|
|
201
|
+
- `estimateCost(request: CompletionRequest): CostEstimate` - Estimate request cost
|
|
202
|
+
|
|
203
|
+
#### OpenAI-Specific Methods
|
|
204
|
+
|
|
205
|
+
- `completionWithFunctions(request & { functions }): Promise<CompletionResponse>` - Chat completion with function calling
|
|
206
|
+
- `analyzeImage(imageUrl: string, prompt: string, model?: string): Promise<CompletionResponse>` - Analyze image with GPT-4 Vision
|
|
207
|
+
|
|
208
|
+
## Available Models
|
|
209
|
+
|
|
210
|
+
### Chat Models
|
|
211
|
+
|
|
212
|
+
- **gpt-4-turbo** - 128K context, latest GPT-4 with improved performance
|
|
213
|
+
- **gpt-4** - 8K context, powerful reasoning and understanding
|
|
214
|
+
- **gpt-4-32k** - 32K context, extended context window
|
|
215
|
+
- **gpt-3.5-turbo** - 16K context, fast and cost-effective
|
|
216
|
+
- **gpt-4-vision-preview** - GPT-4 with vision capabilities
|
|
217
|
+
|
|
218
|
+
### Embedding Models
|
|
219
|
+
|
|
220
|
+
- **text-embedding-3-small** - 1536 dimensions, cost-effective embeddings
|
|
221
|
+
- **text-embedding-3-large** - 3072 dimensions, higher quality embeddings
|
|
222
|
+
- **text-embedding-ada-002** - 1536 dimensions, legacy embedding model
|
|
223
|
+
|
|
224
|
+
## Pricing
|
|
225
|
+
|
|
226
|
+
Pricing is automatically handled based on the model used:
|
|
227
|
+
|
|
228
|
+
- **GPT-4 Turbo**: $0.01/1K input tokens, $0.03/1K output tokens
|
|
229
|
+
- **GPT-4**: $0.03/1K input tokens, $0.06/1K output tokens
|
|
230
|
+
- **GPT-3.5 Turbo**: $0.0005/1K input tokens, $0.0015/1K output tokens
|
|
231
|
+
- **Embeddings (3-small)**: $0.00002/1K tokens
|
|
232
|
+
- **Embeddings (3-large)**: $0.00013/1K tokens
|
|
233
|
+
|
|
234
|
+
## Error Handling
|
|
235
|
+
|
|
236
|
+
The package provides comprehensive error handling:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
try {
|
|
240
|
+
const response = await provider.complete({ messages: [...] });
|
|
241
|
+
if (!response.success) {
|
|
242
|
+
console.error('Error:', response.error);
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
// Handles network errors, timeouts, etc.
|
|
246
|
+
console.error('Request failed:', error);
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Error codes:
|
|
251
|
+
- `INVALID_REQUEST` - Invalid request parameters
|
|
252
|
+
- `AUTHENTICATION_ERROR` - Invalid API key
|
|
253
|
+
- `PERMISSION_DENIED` - Insufficient permissions
|
|
254
|
+
- `NOT_FOUND` - Model or resource not found
|
|
255
|
+
- `RATE_LIMIT_ERROR` - Rate limit exceeded (retryable)
|
|
256
|
+
- `SERVER_ERROR` - OpenAI server error (retryable)
|
|
257
|
+
- `TIMEOUT_ERROR` - Request timeout (retryable)
|
|
258
|
+
|
|
259
|
+
## Integration Status
|
|
260
|
+
|
|
261
|
+
- **Logger**: Required - Uses @bernierllc/logger for operation logging
|
|
262
|
+
- **Docs-Suite**: Ready - Full API documentation available
|
|
263
|
+
- **NeverHub**: Optional - Service discovery and event publishing supported
|
|
264
|
+
|
|
265
|
+
## Development
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Install dependencies
|
|
269
|
+
pnpm install
|
|
270
|
+
|
|
271
|
+
# Build package
|
|
272
|
+
pnpm run build
|
|
273
|
+
|
|
274
|
+
# Run tests
|
|
275
|
+
pnpm test
|
|
276
|
+
|
|
277
|
+
# Run tests with coverage
|
|
278
|
+
pnpm run test:coverage
|
|
279
|
+
|
|
280
|
+
# Lint code
|
|
281
|
+
pnpm run lint
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
Copyright (c) 2025 Bernier LLC. All rights reserved.
|
|
287
|
+
|
|
288
|
+
This package is part of the BernierLLC tools monorepo and follows the unified AI provider interface pattern for seamless provider switching and integration.
|
|
289
|
+
|
|
290
|
+
## See Also
|
|
291
|
+
|
|
292
|
+
- [@bernierllc/ai-provider-core](../ai-provider-core) - Abstract AI provider interface
|
|
293
|
+
- [@bernierllc/ai-provider-anthropic](../ai-provider-anthropic) - Anthropic Claude provider
|
|
294
|
+
- [@bernierllc/ai-content-generator](../../service/ai-content-generator) - AI-powered content generation service
|