@bedrockio/ai 0.3.0 → 0.4.4
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/CHANGELOG.md +25 -0
- package/README.md +58 -17
- package/dist/cjs/BaseClient.js +242 -182
- package/dist/cjs/anthropic.js +115 -93
- package/dist/cjs/google.js +74 -80
- package/dist/cjs/index.js +23 -75
- package/dist/cjs/openai.js +114 -72
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/utils/code.js +11 -0
- package/dist/cjs/utils/json.js +53 -0
- package/dist/cjs/utils/templates.js +83 -0
- package/dist/cjs/xai.js +11 -20
- package/dist/esm/BaseClient.js +243 -0
- package/dist/esm/anthropic.js +116 -0
- package/dist/esm/google.js +75 -0
- package/dist/esm/index.js +25 -0
- package/dist/esm/openai.js +113 -0
- package/dist/esm/utils/code.js +8 -0
- package/dist/esm/utils/json.js +50 -0
- package/dist/esm/utils/templates.js +76 -0
- package/dist/esm/xai.js +10 -0
- package/package.json +25 -18
- package/types/BaseClient.d.ts +67 -26
- package/types/BaseClient.d.ts.map +1 -1
- package/types/anthropic.d.ts +26 -2
- package/types/anthropic.d.ts.map +1 -1
- package/types/google.d.ts.map +1 -1
- package/types/index.d.ts +4 -11
- package/types/index.d.ts.map +1 -1
- package/types/openai.d.ts +45 -2
- package/types/openai.d.ts.map +1 -1
- package/types/utils/code.d.ts +2 -0
- package/types/utils/code.d.ts.map +1 -0
- package/types/utils/json.d.ts +2 -0
- package/types/utils/json.d.ts.map +1 -0
- package/types/utils/templates.d.ts +3 -0
- package/types/utils/templates.d.ts.map +1 -0
- package/types/utils.d.ts +4 -0
- package/types/utils.d.ts.map +1 -0
- package/types/xai.d.ts.map +1 -1
- package/.prettierignore +0 -1
- package/.prettierrc.cjs +0 -1
- package/__mocks__/@anthropic-ai/sdk.js +0 -43
- package/__mocks__/@google/generative-ai.js +0 -59
- package/__mocks__/openai.js +0 -48
- package/dist/cjs/util.js +0 -62
- package/src/BaseClient.js +0 -195
- package/src/anthropic.js +0 -97
- package/src/google.js +0 -91
- package/src/index.js +0 -72
- package/src/openai.js +0 -71
- package/src/util.js +0 -60
- package/src/xai.js +0 -19
package/dist/cjs/anthropic.js
CHANGED
|
@@ -1,101 +1,123 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AnthropicClient = void 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
super(options);
|
|
16
|
-
this.client = new _sdk.default({
|
|
17
|
-
...options
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Lists available models.
|
|
23
|
-
* {@link https://docs.anthropic.com/en/docs/about-claude/models Documentation}
|
|
24
|
-
*/
|
|
25
|
-
async models() {
|
|
26
|
-
const {
|
|
27
|
-
data
|
|
28
|
-
} = await this.client.models.list();
|
|
29
|
-
return data.map(o => o.id);
|
|
30
|
-
}
|
|
31
|
-
async getCompletion(options) {
|
|
32
|
-
const {
|
|
33
|
-
model = DEFAULT_MODEL,
|
|
34
|
-
max_tokens = 2048,
|
|
35
|
-
output = 'text',
|
|
36
|
-
stream = false,
|
|
37
|
-
messages
|
|
38
|
-
} = options;
|
|
39
|
-
const {
|
|
40
|
-
client
|
|
41
|
-
} = this;
|
|
42
|
-
const {
|
|
43
|
-
system,
|
|
44
|
-
user
|
|
45
|
-
} = splitMessages(messages);
|
|
46
|
-
if (!model) {
|
|
47
|
-
throw new Error(`No model specified. Available models are here: ${MODELS_URL}.`);
|
|
7
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
8
|
+
const BaseClient_js_1 = __importDefault(require("./BaseClient.js"));
|
|
9
|
+
const DEFAULT_TOKENS = 4096;
|
|
10
|
+
class AnthropicClient extends BaseClient_js_1.default {
|
|
11
|
+
static DEFAULT_MODEL = 'claude-sonnet-4-5';
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super(options);
|
|
14
|
+
this.client = new sdk_1.default(options);
|
|
48
15
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (output === 'raw') {
|
|
57
|
-
return response;
|
|
16
|
+
/**
|
|
17
|
+
* Lists available models.
|
|
18
|
+
* {@link https://docs.anthropic.com/en/docs/about-claude/models Documentation}
|
|
19
|
+
*/
|
|
20
|
+
async models() {
|
|
21
|
+
const { data } = await this.client.models.list();
|
|
22
|
+
return data.map((o) => o.id);
|
|
58
23
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (chunk.type === 'content_block_start') {
|
|
72
|
-
type = 'start';
|
|
73
|
-
} else if (chunk.type === 'content_block_delta') {
|
|
74
|
-
type = 'chunk';
|
|
75
|
-
} else if (chunk.type === 'message_stop') {
|
|
76
|
-
type = 'stop';
|
|
24
|
+
async runPrompt(options) {
|
|
25
|
+
const { input, model, temperature, instructions, stream = false, tokens = DEFAULT_TOKENS, } = options;
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
return await this.client.messages.create({
|
|
28
|
+
model,
|
|
29
|
+
stream,
|
|
30
|
+
temperature,
|
|
31
|
+
max_tokens: tokens,
|
|
32
|
+
system: instructions,
|
|
33
|
+
...this.getSchemaOptions(options),
|
|
34
|
+
messages: input,
|
|
35
|
+
});
|
|
77
36
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
37
|
+
async runStream(options) {
|
|
38
|
+
return await this.runPrompt({
|
|
39
|
+
...options,
|
|
40
|
+
output: 'raw',
|
|
41
|
+
stream: true,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
getTextResponse(response) {
|
|
45
|
+
const textBlock = response.content.find((block) => {
|
|
46
|
+
return block.type === 'text';
|
|
47
|
+
});
|
|
48
|
+
return textBlock?.text || null;
|
|
49
|
+
}
|
|
50
|
+
getStructuredResponse(response) {
|
|
51
|
+
const toolBlock = response.content.find((block) => {
|
|
52
|
+
return block.type === 'tool_use';
|
|
53
|
+
});
|
|
54
|
+
return toolBlock?.input || null;
|
|
55
|
+
}
|
|
56
|
+
getMessagesResponse(input, response) {
|
|
57
|
+
return {
|
|
58
|
+
messages: [
|
|
59
|
+
...input,
|
|
60
|
+
...response.content
|
|
61
|
+
.filter((item) => {
|
|
62
|
+
return item.type === 'text';
|
|
63
|
+
})
|
|
64
|
+
.map((item) => {
|
|
65
|
+
return {
|
|
66
|
+
role: 'assistant',
|
|
67
|
+
content: item.text,
|
|
68
|
+
};
|
|
69
|
+
}),
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
normalizeStreamEvent(event) {
|
|
74
|
+
let { type } = event;
|
|
75
|
+
if (type === 'content_block_start') {
|
|
76
|
+
return {
|
|
77
|
+
type: 'start',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else if (type === 'content_block_stop') {
|
|
81
|
+
return {
|
|
82
|
+
type: 'stop',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else if (type === 'content_block_delta') {
|
|
86
|
+
return {
|
|
87
|
+
type: 'delta',
|
|
88
|
+
text: event.delta.text,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Private
|
|
93
|
+
getSchemaOptions(options) {
|
|
94
|
+
const { output } = options;
|
|
95
|
+
if (output?.type) {
|
|
96
|
+
let schema = output;
|
|
97
|
+
if (schema.type === 'array') {
|
|
98
|
+
schema = {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {
|
|
101
|
+
items: schema,
|
|
102
|
+
},
|
|
103
|
+
required: ['items'],
|
|
104
|
+
additionalProperties: false,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
tools: [
|
|
109
|
+
{
|
|
110
|
+
name: 'schema',
|
|
111
|
+
description: 'Follow the schema for JSON output.',
|
|
112
|
+
input_schema: schema,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
tool_choice: {
|
|
116
|
+
type: 'tool',
|
|
117
|
+
name: 'schema',
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
83
121
|
}
|
|
84
|
-
}
|
|
85
122
|
}
|
|
86
123
|
exports.AnthropicClient = AnthropicClient;
|
|
87
|
-
function splitMessages(messages) {
|
|
88
|
-
const system = [];
|
|
89
|
-
const user = [];
|
|
90
|
-
for (let message of messages) {
|
|
91
|
-
if (message.role === 'system') {
|
|
92
|
-
system.push(message);
|
|
93
|
-
} else {
|
|
94
|
-
user.push(message);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
system: system.join('\n'),
|
|
99
|
-
user
|
|
100
|
-
};
|
|
101
|
-
}
|
package/dist/cjs/google.js
CHANGED
|
@@ -1,88 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.GoogleClient = void 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var _util = require("./util.js");
|
|
10
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
const generative_ai_1 = require("@google/generative-ai");
|
|
8
|
+
const BaseClient_js_1 = __importDefault(require("./BaseClient.js"));
|
|
11
9
|
const DEFAULT_MODEL = 'models/gemini-2.0-flash-exp';
|
|
12
|
-
class GoogleClient extends
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} = options;
|
|
18
|
-
this.client = new _generativeAi.GoogleGenerativeAI(apiKey);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Lists available models.
|
|
23
|
-
* {@link https://ai.google.dev/gemini-api/docs/models/gemini#gemini-2.0-flashl Documentation}
|
|
24
|
-
*/
|
|
25
|
-
async models() {
|
|
26
|
-
return ['gemini-2.0-flash-exp', 'gemini-1.5-flash', 'gemini-1.5-flash-8b', 'gemini-1.5-pro'];
|
|
27
|
-
}
|
|
28
|
-
async getCompletion(options) {
|
|
29
|
-
const {
|
|
30
|
-
model = DEFAULT_MODEL,
|
|
31
|
-
output = 'text',
|
|
32
|
-
stream = false
|
|
33
|
-
} = options;
|
|
34
|
-
const {
|
|
35
|
-
client
|
|
36
|
-
} = this;
|
|
37
|
-
const generator = client.getGenerativeModel({
|
|
38
|
-
model
|
|
39
|
-
});
|
|
40
|
-
const messages = await this.getMessages(options);
|
|
41
|
-
const prompts = messages.map(message => {
|
|
42
|
-
return message.content;
|
|
43
|
-
});
|
|
44
|
-
let response;
|
|
45
|
-
if (stream) {
|
|
46
|
-
response = await generator.generateContentStream(prompts);
|
|
47
|
-
} else {
|
|
48
|
-
response = await generator.generateContent(prompts);
|
|
10
|
+
class GoogleClient extends BaseClient_js_1.default {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super(options);
|
|
13
|
+
const { apiKey } = options;
|
|
14
|
+
this.client = new generative_ai_1.GoogleGenerativeAI(apiKey);
|
|
49
15
|
}
|
|
50
|
-
|
|
51
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Lists available models.
|
|
18
|
+
* {@link https://ai.google.dev/gemini-api/docs/models/gemini#gemini-2.0-flashl Documentation}
|
|
19
|
+
*/
|
|
20
|
+
async models() {
|
|
21
|
+
return [
|
|
22
|
+
'gemini-2.0-flash-exp',
|
|
23
|
+
'gemini-1.5-flash',
|
|
24
|
+
'gemini-1.5-flash-8b',
|
|
25
|
+
'gemini-1.5-pro',
|
|
26
|
+
];
|
|
52
27
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
28
|
+
async getCompletion(options) {
|
|
29
|
+
const { model = DEFAULT_MODEL, output = 'text', stream = false } = options;
|
|
30
|
+
const { client } = this;
|
|
31
|
+
const generator = client.getGenerativeModel({
|
|
32
|
+
model,
|
|
33
|
+
});
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
const messages = await this.getMessages(options);
|
|
36
|
+
const prompts = messages.map((message) => {
|
|
37
|
+
return message.content;
|
|
38
|
+
});
|
|
39
|
+
let response;
|
|
40
|
+
if (stream) {
|
|
41
|
+
response = await generator.generateContentStream(prompts);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
response = await generator.generateContent(prompts);
|
|
45
|
+
}
|
|
46
|
+
if (output === 'raw') {
|
|
47
|
+
return response;
|
|
48
|
+
}
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
const parts = response.response.candidates.flatMap((candidate) => {
|
|
51
|
+
return candidate.content.parts;
|
|
52
|
+
});
|
|
53
|
+
const [message] = parts;
|
|
54
|
+
return message;
|
|
79
55
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
56
|
+
async getStream(options) {
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
const response = await super.getStream(options);
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
return response.stream;
|
|
61
|
+
}
|
|
62
|
+
getStreamedChunk(chunk, started) {
|
|
63
|
+
const [candidate] = chunk.candidates;
|
|
64
|
+
let type;
|
|
65
|
+
if (!started) {
|
|
66
|
+
type = 'start';
|
|
67
|
+
}
|
|
68
|
+
else if (candidate.finishReason === 'STOP') {
|
|
69
|
+
type = 'stop';
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
type = 'chunk';
|
|
73
|
+
}
|
|
74
|
+
if (type) {
|
|
75
|
+
return {
|
|
76
|
+
type,
|
|
77
|
+
text: candidate.content.parts[0].text || '',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
85
80
|
}
|
|
86
|
-
}
|
|
87
81
|
}
|
|
88
|
-
exports.GoogleClient = GoogleClient;
|
|
82
|
+
exports.GoogleClient = GoogleClient;
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,80 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
constructor(options = {}) {
|
|
13
|
-
if (!options.platform) {
|
|
14
|
-
throw new Error('No platform specified.');
|
|
15
|
-
} else if (!options.templates) {
|
|
16
|
-
throw new Error('No templates directory specified.');
|
|
17
|
-
} else if (!options.apiKey) {
|
|
18
|
-
throw new Error('No API key specified.');
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createClient = createClient;
|
|
4
|
+
const anthropic_js_1 = require("./anthropic.js");
|
|
5
|
+
const google_js_1 = require("./google.js");
|
|
6
|
+
const openai_js_1 = require("./openai.js");
|
|
7
|
+
const xai_js_1 = require("./xai.js");
|
|
8
|
+
function createClient(options = {}) {
|
|
9
|
+
const { platform } = options;
|
|
10
|
+
if (!platform) {
|
|
11
|
+
throw new Error('No platform specified.');
|
|
19
12
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const {
|
|
32
|
-
name,
|
|
33
|
-
apiKey
|
|
34
|
-
} = platform;
|
|
35
|
-
const client = getClientForPlatform({
|
|
36
|
-
...options,
|
|
37
|
-
platform: name,
|
|
38
|
-
apiKey
|
|
39
|
-
});
|
|
40
|
-
this.clients[name] = client;
|
|
41
|
-
this.clients[undefined] ||= client;
|
|
13
|
+
if (platform === 'openai' || platform === 'gpt') {
|
|
14
|
+
return new openai_js_1.OpenAiClient(options);
|
|
15
|
+
}
|
|
16
|
+
else if (platform === 'google' || platform === 'gemini') {
|
|
17
|
+
return new google_js_1.GoogleClient(options);
|
|
18
|
+
}
|
|
19
|
+
else if (platform === 'anthropic' || platform === 'claude') {
|
|
20
|
+
return new anthropic_js_1.AnthropicClient(options);
|
|
21
|
+
}
|
|
22
|
+
else if (platform === 'xai' || platform === 'grok') {
|
|
23
|
+
return new xai_js_1.XAiClient(options);
|
|
42
24
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return this.getClient(options).prompt(options);
|
|
46
|
-
}
|
|
47
|
-
stream(options) {
|
|
48
|
-
return this.getClient(options).stream(options);
|
|
49
|
-
}
|
|
50
|
-
buildTemplate(options) {
|
|
51
|
-
return this.getClient(options).buildTemplate(options);
|
|
52
|
-
}
|
|
53
|
-
getClient(options) {
|
|
54
|
-
const {
|
|
55
|
-
platform
|
|
56
|
-
} = options;
|
|
57
|
-
const client = this.clients[platform];
|
|
58
|
-
if (!client) {
|
|
59
|
-
throw new Error(`Platform "${platform}" not found.`);
|
|
25
|
+
else if (platform) {
|
|
26
|
+
throw new Error(`Unknown platform "${platform}".`);
|
|
60
27
|
}
|
|
61
|
-
return client;
|
|
62
|
-
}
|
|
63
28
|
}
|
|
64
|
-
exports.MultiClient = MultiClient;
|
|
65
|
-
function getClientForPlatform(options) {
|
|
66
|
-
const {
|
|
67
|
-
platform
|
|
68
|
-
} = options;
|
|
69
|
-
if (platform === 'openai' || platform === 'gpt') {
|
|
70
|
-
return new _openai.OpenAiClient(options);
|
|
71
|
-
} else if (platform === 'google' || platform === 'gemini') {
|
|
72
|
-
return new _google.GoogleClient(options);
|
|
73
|
-
} else if (platform === 'anthropic' || platform === 'claude') {
|
|
74
|
-
return new _anthropic.AnthropicClient(options);
|
|
75
|
-
} else if (platform === 'xai' || platform === 'grok') {
|
|
76
|
-
return new _xai.XAiClient(options);
|
|
77
|
-
} else if (platform) {
|
|
78
|
-
throw new Error(`Unknown platform "${platform}".`);
|
|
79
|
-
}
|
|
80
|
-
}
|
package/dist/cjs/openai.js
CHANGED
|
@@ -1,78 +1,120 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.OpenAiClient = void 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
super(options);
|
|
15
|
-
this.client = new _openai.default({
|
|
16
|
-
...options
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Lists available models.
|
|
22
|
-
* {@link https://platform.openai.com/docs/models Documentation}
|
|
23
|
-
*/
|
|
24
|
-
async models() {
|
|
25
|
-
const {
|
|
26
|
-
data
|
|
27
|
-
} = await this.client.models.list();
|
|
28
|
-
return data.map(o => o.id);
|
|
29
|
-
}
|
|
30
|
-
async getCompletion(options) {
|
|
31
|
-
const {
|
|
32
|
-
model = DEFAULT_MODEL,
|
|
33
|
-
output = 'text',
|
|
34
|
-
stream = false
|
|
35
|
-
} = options;
|
|
36
|
-
const {
|
|
37
|
-
client
|
|
38
|
-
} = this;
|
|
39
|
-
const messages = await this.getMessages(options);
|
|
40
|
-
const response = await client.chat.completions.create({
|
|
41
|
-
model,
|
|
42
|
-
messages,
|
|
43
|
-
stream,
|
|
44
|
-
response_format: {
|
|
45
|
-
type: output === 'json' ? 'json_object' : 'text'
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
if (output === 'raw') {
|
|
49
|
-
return response;
|
|
7
|
+
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const BaseClient_js_1 = __importDefault(require("./BaseClient.js"));
|
|
9
|
+
class OpenAiClient extends BaseClient_js_1.default {
|
|
10
|
+
static DEFAULT_MODEL = 'gpt-5-nano';
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super(options);
|
|
13
|
+
this.client = new openai_1.default(options);
|
|
50
14
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
getStreamedChunk(chunk, started) {
|
|
61
|
-
const [choice] = chunk.choices;
|
|
62
|
-
let type;
|
|
63
|
-
if (!started) {
|
|
64
|
-
type = 'start';
|
|
65
|
-
} else if (choice.finish_reason === 'stop') {
|
|
66
|
-
type = 'stop';
|
|
67
|
-
} else {
|
|
68
|
-
type = 'chunk';
|
|
15
|
+
/**
|
|
16
|
+
* Lists available models.
|
|
17
|
+
* {@link https://platform.openai.com/docs/models Documentation}
|
|
18
|
+
*/
|
|
19
|
+
async models() {
|
|
20
|
+
const { data } = await this.client.models.list();
|
|
21
|
+
return data.map((o) => o.id);
|
|
69
22
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
23
|
+
async runPrompt(options) {
|
|
24
|
+
const { input, model, tools, verbosity, temperature, instructions, prevResponseId, stream = false, } = options;
|
|
25
|
+
const params = {
|
|
26
|
+
model,
|
|
27
|
+
input,
|
|
28
|
+
tools,
|
|
29
|
+
stream,
|
|
30
|
+
temperature,
|
|
31
|
+
instructions,
|
|
32
|
+
previous_response_id: prevResponseId,
|
|
33
|
+
text: {
|
|
34
|
+
format: this.getOutputFormat(options),
|
|
35
|
+
verbosity,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
this.debug('Params:', params);
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
return await this.client.responses.create(params);
|
|
41
|
+
}
|
|
42
|
+
async runStream(options) {
|
|
43
|
+
return await this.runPrompt({
|
|
44
|
+
...options,
|
|
45
|
+
stream: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
getTextResponse(response) {
|
|
49
|
+
return response.output_text;
|
|
50
|
+
}
|
|
51
|
+
getStructuredResponse(response) {
|
|
52
|
+
return JSON.parse(response.output_text);
|
|
53
|
+
}
|
|
54
|
+
getMessagesResponse(input, response) {
|
|
55
|
+
return {
|
|
56
|
+
messages: [
|
|
57
|
+
...input,
|
|
58
|
+
{
|
|
59
|
+
role: 'assistant',
|
|
60
|
+
content: response.output_text,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
// Note that this ability currently only
|
|
64
|
+
// exists for OpenAI compatible providers.
|
|
65
|
+
prevResponseId: response.id,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Private
|
|
69
|
+
getOutputFormat(options) {
|
|
70
|
+
let { output, schema } = options;
|
|
71
|
+
if (output === 'json') {
|
|
72
|
+
return {
|
|
73
|
+
type: 'json_object',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
else if (schema) {
|
|
77
|
+
return {
|
|
78
|
+
type: 'json_schema',
|
|
79
|
+
// Name is required but arbitrary.
|
|
80
|
+
name: 'schema',
|
|
81
|
+
strict: true,
|
|
82
|
+
schema,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return {
|
|
87
|
+
type: 'text',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
normalizeStreamEvent(event) {
|
|
92
|
+
const { type } = event;
|
|
93
|
+
if (type === 'response.created') {
|
|
94
|
+
return {
|
|
95
|
+
type: 'start',
|
|
96
|
+
id: event.response.id,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
else if (type === 'response.completed') {
|
|
100
|
+
return {
|
|
101
|
+
type: 'stop',
|
|
102
|
+
id: event.response.id,
|
|
103
|
+
usage: event.response.usage,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
else if (type === 'response.output_text.delta') {
|
|
107
|
+
return {
|
|
108
|
+
type: 'delta',
|
|
109
|
+
delta: event.delta,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
else if (type === 'response.output_text.done') {
|
|
113
|
+
return {
|
|
114
|
+
type: 'done',
|
|
115
|
+
text: event.text,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
75
118
|
}
|
|
76
|
-
}
|
|
77
119
|
}
|
|
78
|
-
exports.OpenAiClient = OpenAiClient;
|
|
120
|
+
exports.OpenAiClient = OpenAiClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|