@crewdle/mist-connector-openai 1.0.0 → 1.0.1
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.
|
@@ -51,24 +51,114 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
51
51
|
if (!options || !this.models.has(options.model.id)) {
|
|
52
52
|
throw new Error('Model not initialized');
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
let tools;
|
|
55
|
+
if (parameters.functions && parameters.functions.size > 0) {
|
|
56
|
+
tools = [];
|
|
57
|
+
for (const [name, func] of parameters.functions) {
|
|
58
|
+
let params;
|
|
59
|
+
if (func.params) {
|
|
60
|
+
params = {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: func.params,
|
|
63
|
+
required: Object.keys(func.params),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
tools.push({
|
|
67
|
+
type: 'function',
|
|
68
|
+
function: {
|
|
69
|
+
name,
|
|
70
|
+
description: func.description,
|
|
71
|
+
parameters: params,
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const messages = this.getMessages(parameters);
|
|
77
|
+
while (true) {
|
|
78
|
+
const stream = await this.client.chat.completions.create({
|
|
79
|
+
model: options.model.id,
|
|
80
|
+
messages,
|
|
81
|
+
max_completion_tokens: parameters.maxTokens,
|
|
82
|
+
temperature: parameters.temperature,
|
|
83
|
+
stream: true,
|
|
84
|
+
stream_options: {
|
|
85
|
+
include_usage: true,
|
|
86
|
+
},
|
|
87
|
+
tools,
|
|
88
|
+
});
|
|
89
|
+
let message = {};
|
|
90
|
+
for await (const chunk of stream) {
|
|
91
|
+
if (chunk.choices[0]?.delta?.tool_calls) {
|
|
92
|
+
message = this.messageReducer(message, chunk);
|
|
93
|
+
}
|
|
94
|
+
yield {
|
|
95
|
+
type: 'prompt',
|
|
96
|
+
output: chunk.choices[0]?.delta?.content ?? '',
|
|
97
|
+
inputTokens: chunk.usage?.prompt_tokens ?? 0,
|
|
98
|
+
outputTokens: chunk.usage?.completion_tokens ?? 0,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (!message.tool_calls) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
messages.push(message);
|
|
105
|
+
const toolCall = message.tool_calls[0];
|
|
106
|
+
if (toolCall?.function) {
|
|
107
|
+
try {
|
|
108
|
+
const result = await parameters.functions.get(toolCall.function.name)?.callback(JSON.parse(toolCall.function.arguments));
|
|
109
|
+
messages.push({
|
|
110
|
+
role: 'tool',
|
|
111
|
+
tool_call_id: toolCall.id,
|
|
112
|
+
content: result ?? '',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('Error processing tool call', error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
messageReducer(previous, item) {
|
|
122
|
+
const reduce = (acc, delta) => {
|
|
123
|
+
acc = { ...acc };
|
|
124
|
+
for (const [key, value] of Object.entries(delta)) {
|
|
125
|
+
if (acc[key] === undefined || acc[key] === null) {
|
|
126
|
+
acc[key] = value;
|
|
127
|
+
// OpenAI.Chat.Completions.ChatCompletionMessageToolCall does not have a key, .index
|
|
128
|
+
if (Array.isArray(acc[key])) {
|
|
129
|
+
for (const arr of acc[key]) {
|
|
130
|
+
delete arr.index;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (typeof acc[key] === 'string' && typeof value === 'string') {
|
|
135
|
+
acc[key] += value;
|
|
136
|
+
}
|
|
137
|
+
else if (typeof acc[key] === 'number' && typeof value === 'number') {
|
|
138
|
+
acc[key] = value;
|
|
139
|
+
}
|
|
140
|
+
else if (Array.isArray(acc[key]) && Array.isArray(value)) {
|
|
141
|
+
const accArray = acc[key];
|
|
142
|
+
for (let i = 0; i < value.length; i++) {
|
|
143
|
+
const { index, ...chunkTool } = value[i];
|
|
144
|
+
if (index - accArray.length > 1) {
|
|
145
|
+
throw new Error(`Error: An array has an empty value when tool_calls are constructed. tool_calls: ${accArray}; tool: ${value}`);
|
|
146
|
+
}
|
|
147
|
+
accArray[index] = reduce(accArray[index], chunkTool);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (typeof acc[key] === 'object' && typeof value === 'object') {
|
|
151
|
+
acc[key] = reduce(acc[key], value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return acc;
|
|
155
|
+
};
|
|
156
|
+
const choice = item.choices[0];
|
|
157
|
+
if (!choice) {
|
|
158
|
+
// chunk contains information about usage and token counts
|
|
159
|
+
return previous;
|
|
71
160
|
}
|
|
161
|
+
return reduce(previous, choice.delta);
|
|
72
162
|
}
|
|
73
163
|
getMessages(parameters) {
|
|
74
164
|
const messages = [];
|
|
@@ -9,5 +9,6 @@ export declare class OpenAIGenerativeAIWorkerConnector implements IGenerativeAIW
|
|
|
9
9
|
getEngineType(): GenerativeAIEngineType;
|
|
10
10
|
processJob(parameters: GenerativeAIWorkerConnectorParameters, options?: IGenerativeAIWorkerOptions): Promise<IGenerativeAIWorkerConnectorPromptResult>;
|
|
11
11
|
processJobStream(parameters: GenerativeAIWorkerConnectorParameters, options?: IGenerativeAIWorkerOptions): AsyncGenerator<IGenerativeAIWorkerConnectorPromptResult>;
|
|
12
|
+
private messageReducer;
|
|
12
13
|
private getMessages;
|
|
13
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewdle/mist-connector-openai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"dist/"
|
|
16
16
|
],
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@crewdle/web-sdk-types": "^1.0.
|
|
18
|
+
"@crewdle/web-sdk-types": "^1.0.34",
|
|
19
19
|
"@types/node": "^22.13.9",
|
|
20
20
|
"typescript": "^5.8.2"
|
|
21
21
|
},
|