@crewdle/mist-connector-openai 1.0.7 → 1.0.9

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.
@@ -47,53 +47,41 @@ export class OpenAIGenerativeAIWorkerConnector {
47
47
  outputTokens: 0,
48
48
  };
49
49
  }
50
- let responseFormat;
51
- if (parameters.grammar) {
52
- if (parameters.grammar === 'json') {
53
- responseFormat = { type: 'json_object' };
54
- }
55
- else if (parameters.grammar === 'if_else') {
56
- responseFormat = {
57
- type: 'json_schema',
58
- json_schema: {
59
- name: 'router_response',
60
- schema: {
61
- type: 'object',
62
- properties: {
63
- 'condition_result': {
64
- type: 'boolean',
65
- }
66
- },
67
- required: ['result'],
68
- additionalProperties: false,
69
- }
70
- }
71
- };
72
- }
73
- else if (parameters.grammar !== 'default') {
74
- responseFormat = {
75
- type: 'json_schema',
76
- json_schema: {
77
- name: 'custom_response',
78
- schema: parameters.grammar,
79
- }
50
+ const responseFormat = this.getResponseFormat(parameters);
51
+ const tools = this.getTools(parameters);
52
+ const messages = this.getMessages(parameters);
53
+ let totalInputTokens = 0;
54
+ let totalOutputTokens = 0;
55
+ let accumulatedOutput = '';
56
+ let currentSequence = -1;
57
+ while (true) {
58
+ currentSequence++;
59
+ const toolChoice = currentSequence === 0 && tools?.some((tool) => tool.function.name.startsWith('getQuestion')) ? 'required' : undefined;
60
+ const response = await this.client.chat.completions.create({
61
+ model: options.model.id,
62
+ messages,
63
+ max_completion_tokens: parameters.maxTokens,
64
+ temperature: parameters.temperature,
65
+ response_format: responseFormat,
66
+ tools,
67
+ tool_choice: toolChoice,
68
+ });
69
+ const message = response.choices[0].message;
70
+ totalInputTokens += response.usage?.prompt_tokens ?? 0;
71
+ totalOutputTokens += response.usage?.completion_tokens ?? 0;
72
+ if (!message.tool_calls) {
73
+ accumulatedOutput += message.content ?? '';
74
+ return {
75
+ type: 'prompt',
76
+ output: accumulatedOutput,
77
+ inputTokens: totalInputTokens,
78
+ outputTokens: totalOutputTokens,
80
79
  };
81
80
  }
81
+ const promises = [];
82
+ this.processToolCalls(promises, message.tool_calls, messages, parameters.functions);
83
+ await Promise.all(promises);
82
84
  }
83
- const messages = this.getMessages(parameters);
84
- const response = await this.client.chat.completions.create({
85
- model: options.model.id,
86
- messages,
87
- max_completion_tokens: parameters.maxTokens,
88
- temperature: parameters.temperature,
89
- response_format: responseFormat,
90
- });
91
- return {
92
- type: 'prompt',
93
- output: response.choices[0].message.content ?? '',
94
- inputTokens: response.usage?.prompt_tokens ?? 0,
95
- outputTokens: response.usage?.completion_tokens ?? 0,
96
- };
97
85
  }
98
86
  async *processJobStream(parameters, options) {
99
87
  if (!this.client) {
@@ -102,63 +90,13 @@ export class OpenAIGenerativeAIWorkerConnector {
102
90
  if (!options || !this.models.has(options.model.id)) {
103
91
  throw new Error('Model not initialized');
104
92
  }
105
- let responseFormat;
106
- if (parameters.grammar) {
107
- if (parameters.grammar === 'json') {
108
- responseFormat = { type: 'json_object' };
109
- }
110
- else if (parameters.grammar === 'if_else') {
111
- responseFormat = {
112
- type: 'json_schema',
113
- json_schema: {
114
- name: 'router_response',
115
- schema: {
116
- type: 'object',
117
- properties: {
118
- 'condition_result': {
119
- type: 'boolean',
120
- }
121
- },
122
- required: ['result'],
123
- additionalProperties: false,
124
- }
125
- }
126
- };
127
- }
128
- else if (parameters.grammar !== 'default') {
129
- responseFormat = {
130
- type: 'json_schema',
131
- json_schema: {
132
- name: 'custom_response',
133
- schema: parameters.grammar,
134
- }
135
- };
136
- }
137
- }
138
- let tools;
139
- if (parameters.functions && parameters.functions.size > 0) {
140
- tools = [];
141
- for (const [name, func] of parameters.functions) {
142
- let params;
143
- if (func.params) {
144
- params = {
145
- type: 'object',
146
- properties: func.params,
147
- required: Object.keys(func.params),
148
- };
149
- }
150
- tools.push({
151
- type: 'function',
152
- function: {
153
- name,
154
- description: func.description,
155
- parameters: params,
156
- }
157
- });
158
- }
159
- }
93
+ const responseFormat = this.getResponseFormat(parameters);
94
+ const tools = this.getTools(parameters);
160
95
  const messages = this.getMessages(parameters);
96
+ let currentSequence = -1;
161
97
  while (true) {
98
+ currentSequence++;
99
+ const toolChoice = (currentSequence === 0 && tools?.some((tool) => tool.function.name.startsWith('getQuestion'))) ? 'required' : undefined;
162
100
  const stream = await this.client.chat.completions.create({
163
101
  model: options.model.id,
164
102
  messages,
@@ -169,6 +107,7 @@ export class OpenAIGenerativeAIWorkerConnector {
169
107
  include_usage: true,
170
108
  },
171
109
  tools,
110
+ tool_choice: toolChoice,
172
111
  response_format: responseFormat,
173
112
  });
174
113
  let message = {};
@@ -186,55 +125,64 @@ export class OpenAIGenerativeAIWorkerConnector {
186
125
  if (!message.tool_calls) {
187
126
  break;
188
127
  }
189
- messages.push({
190
- role: 'assistant',
191
- content: null,
192
- tool_calls: message.tool_calls,
193
- refusal: null,
194
- });
195
128
  const promises = [];
196
- for (const toolCall of message.tool_calls) {
197
- if (toolCall?.function && parameters.functions) {
198
- try {
199
- const func = parameters.functions.get(toolCall.function.name);
200
- if (func) {
201
- const result = func.callback(JSON.parse(toolCall.function.arguments));
202
- if (result instanceof Promise) {
203
- promises.push(result.then((res) => {
204
- messages.push({
205
- role: 'tool',
206
- tool_call_id: toolCall.id,
207
- content: res ?? 'Tool does not exist',
208
- });
209
- }));
210
- }
211
- else {
129
+ this.processToolCalls(promises, message.tool_calls, messages, parameters.functions);
130
+ await Promise.all(promises);
131
+ yield {
132
+ type: "prompt" /* GenerativeAIJobType.Prompt */,
133
+ output: '\n\n',
134
+ inputTokens: 0,
135
+ outputTokens: 0,
136
+ };
137
+ }
138
+ }
139
+ processToolCalls(promises, toolCalls, messages, functions) {
140
+ messages.push({
141
+ role: 'assistant',
142
+ content: null,
143
+ tool_calls: toolCalls,
144
+ refusal: null,
145
+ });
146
+ for (const toolCall of toolCalls) {
147
+ if (toolCall?.function && functions) {
148
+ try {
149
+ const func = functions.get(toolCall.function.name);
150
+ if (func) {
151
+ const result = func.callback(JSON.parse(toolCall.function.arguments));
152
+ if (result instanceof Promise) {
153
+ promises.push(result.then((res) => {
212
154
  messages.push({
213
155
  role: 'tool',
214
156
  tool_call_id: toolCall.id,
215
- content: result ?? 'Tool does not exist',
157
+ content: res ?? 'Tool does not exist',
216
158
  });
217
- }
159
+ }));
218
160
  }
219
161
  else {
220
162
  messages.push({
221
163
  role: 'tool',
222
164
  tool_call_id: toolCall.id,
223
- content: 'Tool does not exist',
165
+ content: result ?? 'Tool does not exist',
224
166
  });
225
167
  }
226
168
  }
227
- catch (error) {
228
- console.error('Error processing tool call', error);
169
+ else {
229
170
  messages.push({
230
171
  role: 'tool',
231
172
  tool_call_id: toolCall.id,
232
- content: 'Error processing tool call',
173
+ content: 'Tool does not exist',
233
174
  });
234
175
  }
235
176
  }
177
+ catch (error) {
178
+ console.error('Error processing tool call', error);
179
+ messages.push({
180
+ role: 'tool',
181
+ tool_call_id: toolCall.id,
182
+ content: 'Error processing tool call',
183
+ });
184
+ }
236
185
  }
237
- await Promise.all(promises);
238
186
  }
239
187
  }
240
188
  messageReducer(previous, item) {
@@ -301,4 +249,65 @@ export class OpenAIGenerativeAIWorkerConnector {
301
249
  });
302
250
  return messages;
303
251
  }
252
+ getTools(parameters) {
253
+ if (!parameters.functions || parameters.functions.size === 0) {
254
+ return undefined;
255
+ }
256
+ const tools = [];
257
+ for (const [name, func] of parameters.functions) {
258
+ let params;
259
+ if (func.params) {
260
+ params = {
261
+ type: 'object',
262
+ properties: func.params,
263
+ required: Object.keys(func.params),
264
+ };
265
+ }
266
+ tools.push({
267
+ type: 'function',
268
+ function: {
269
+ name,
270
+ description: func.description,
271
+ parameters: params,
272
+ }
273
+ });
274
+ }
275
+ return tools;
276
+ }
277
+ getResponseFormat(parameters) {
278
+ if (!parameters.grammar) {
279
+ return undefined;
280
+ }
281
+ if (parameters.grammar === 'json') {
282
+ return { type: 'json_object' };
283
+ }
284
+ if (parameters.grammar === 'if_else') {
285
+ return {
286
+ type: 'json_schema',
287
+ json_schema: {
288
+ name: 'router_response',
289
+ schema: {
290
+ type: 'object',
291
+ properties: {
292
+ 'condition_result': {
293
+ type: 'boolean',
294
+ }
295
+ },
296
+ required: ['result'],
297
+ additionalProperties: false,
298
+ }
299
+ }
300
+ };
301
+ }
302
+ if (parameters.grammar !== 'default') {
303
+ return {
304
+ type: 'json_schema',
305
+ json_schema: {
306
+ name: 'custom_response',
307
+ schema: parameters.grammar,
308
+ }
309
+ };
310
+ }
311
+ return undefined;
312
+ }
304
313
  }
@@ -9,6 +9,9 @@ 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 processToolCalls;
12
13
  private messageReducer;
13
14
  private getMessages;
15
+ private getTools;
16
+ private getResponseFormat;
14
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewdle/mist-connector-openai",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
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.37",
18
+ "@crewdle/web-sdk-types": "^1.0.38",
19
19
  "@types/node": "^22.13.9",
20
20
  "typescript": "^5.8.2"
21
21
  },