openai 4.20.1 → 4.22.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/CHANGELOG.md +37 -0
- package/README.md +3 -3
- package/error.d.ts.map +1 -1
- package/error.js +2 -1
- package/error.js.map +1 -1
- package/error.mjs +2 -1
- package/error.mjs.map +1 -1
- package/index.d.mts +7 -5
- package/index.d.ts +7 -5
- package/index.d.ts.map +1 -1
- package/index.js +5 -5
- package/index.js.map +1 -1
- package/index.mjs +5 -5
- package/index.mjs.map +1 -1
- package/lib/AbstractChatCompletionRunner.d.ts +1 -1
- package/lib/AbstractChatCompletionRunner.d.ts.map +1 -1
- package/lib/AbstractChatCompletionRunner.js +21 -6
- package/lib/AbstractChatCompletionRunner.js.map +1 -1
- package/lib/AbstractChatCompletionRunner.mjs +21 -6
- package/lib/AbstractChatCompletionRunner.mjs.map +1 -1
- package/lib/ChatCompletionRunFunctions.test.js +823 -549
- package/lib/ChatCompletionRunFunctions.test.js.map +1 -1
- package/lib/ChatCompletionRunFunctions.test.mjs +824 -550
- package/lib/ChatCompletionRunFunctions.test.mjs.map +1 -1
- package/lib/ChatCompletionRunner.d.ts +1 -0
- package/lib/ChatCompletionRunner.d.ts.map +1 -1
- package/lib/ChatCompletionRunner.js +11 -2
- package/lib/ChatCompletionRunner.js.map +1 -1
- package/lib/ChatCompletionRunner.mjs +11 -2
- package/lib/ChatCompletionRunner.mjs.map +1 -1
- package/lib/ChatCompletionStreamingRunner.d.ts +1 -0
- package/lib/ChatCompletionStreamingRunner.d.ts.map +1 -1
- package/lib/ChatCompletionStreamingRunner.js +7 -4
- package/lib/ChatCompletionStreamingRunner.js.map +1 -1
- package/lib/ChatCompletionStreamingRunner.mjs +7 -4
- package/lib/ChatCompletionStreamingRunner.mjs.map +1 -1
- package/lib/RunnableFunction.d.ts +19 -3
- package/lib/RunnableFunction.d.ts.map +1 -1
- package/lib/RunnableFunction.js +14 -1
- package/lib/RunnableFunction.js.map +1 -1
- package/lib/RunnableFunction.mjs +12 -0
- package/lib/RunnableFunction.mjs.map +1 -1
- package/package.json +3 -2
- package/resources/audio/speech.d.ts +3 -1
- package/resources/audio/speech.d.ts.map +1 -1
- package/resources/audio/speech.js.map +1 -1
- package/resources/audio/speech.mjs.map +1 -1
- package/resources/beta/chat/completions.d.ts +2 -8
- package/resources/beta/chat/completions.d.ts.map +1 -1
- package/resources/beta/chat/completions.js +2 -1
- package/resources/beta/chat/completions.js.map +1 -1
- package/resources/beta/chat/completions.mjs +1 -1
- package/resources/beta/chat/completions.mjs.map +1 -1
- package/resources/chat/completions.d.ts +52 -34
- package/resources/chat/completions.d.ts.map +1 -1
- package/resources/chat/completions.js.map +1 -1
- package/resources/chat/completions.mjs.map +1 -1
- package/resources/completions.d.ts +2 -2
- package/resources/embeddings.d.ts +2 -1
- package/resources/embeddings.d.ts.map +1 -1
- package/resources/embeddings.js.map +1 -1
- package/resources/embeddings.mjs.map +1 -1
- package/resources/files.d.ts +3 -3
- package/resources/files.js +3 -3
- package/resources/files.mjs +3 -3
- package/resources/shared.d.ts +12 -14
- package/resources/shared.d.ts.map +1 -1
- package/src/error.ts +2 -1
- package/src/index.ts +8 -5
- package/src/lib/AbstractChatCompletionRunner.ts +37 -13
- package/src/lib/ChatCompletionRunFunctions.test.ts +828 -558
- package/src/lib/ChatCompletionRunner.ts +11 -2
- package/src/lib/ChatCompletionStreamingRunner.ts +11 -12
- package/src/lib/RunnableFunction.ts +33 -7
- package/src/resources/audio/speech.ts +3 -1
- package/src/resources/beta/chat/completions.ts +2 -7
- package/src/resources/chat/completions.ts +56 -35
- package/src/resources/completions.ts +2 -2
- package/src/resources/embeddings.ts +2 -1
- package/src/resources/files.ts +3 -3
- package/src/resources/shared.ts +13 -15
- package/src/streaming.ts +4 -1
- package/src/uploads.ts +2 -3
- package/src/version.ts +1 -1
- package/streaming.d.ts.map +1 -1
- package/streaming.js.map +1 -1
- package/streaming.mjs.map +1 -1
- package/uploads.d.ts.map +1 -1
- package/uploads.js +2 -1
- package/uploads.js.map +1 -1
- package/uploads.mjs +2 -1
- package/uploads.mjs.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -2,7 +2,7 @@ import OpenAI from 'openai';
|
|
|
2
2
|
import { OpenAIError } from "../error";
|
|
3
3
|
import { PassThrough } from 'stream';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
ParsingToolFunction,
|
|
6
6
|
type ChatCompletionRunner,
|
|
7
7
|
type ChatCompletionFunctionRunnerParams,
|
|
8
8
|
ChatCompletionStreamingRunner,
|
|
@@ -63,10 +63,13 @@ function mockFetch(): { fetch: Fetch; handleRequest: (handle: Fetch) => Promise<
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function handleRequest(handle: typeof fetch): Promise<void> {
|
|
66
|
-
return new Promise<void>((resolve) => {
|
|
66
|
+
return new Promise<void>((resolve, reject) => {
|
|
67
67
|
fetchQueue.shift()?.(async (req, init) => {
|
|
68
68
|
try {
|
|
69
69
|
return await handle(req, init);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
reject(err);
|
|
72
|
+
return err as any;
|
|
70
73
|
} finally {
|
|
71
74
|
resolve();
|
|
72
75
|
}
|
|
@@ -157,10 +160,12 @@ function* functionCallDeltas(
|
|
|
157
160
|
args: string,
|
|
158
161
|
{
|
|
159
162
|
index = 0,
|
|
163
|
+
id = '123',
|
|
160
164
|
name,
|
|
161
165
|
role = 'assistant',
|
|
162
166
|
}: {
|
|
163
167
|
name: string;
|
|
168
|
+
id?: string;
|
|
164
169
|
index?: number;
|
|
165
170
|
role?: NonNullable<OpenAI.Chat.ChatCompletionChunk.Choice.Delta['role']>;
|
|
166
171
|
},
|
|
@@ -172,10 +177,17 @@ function* functionCallDeltas(
|
|
|
172
177
|
finish_reason: i === deltas.length - 1 ? 'function_call' : null,
|
|
173
178
|
delta: {
|
|
174
179
|
role,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
180
|
+
tool_calls: [
|
|
181
|
+
{
|
|
182
|
+
type: 'function',
|
|
183
|
+
index: 0,
|
|
184
|
+
id,
|
|
185
|
+
function: {
|
|
186
|
+
arguments: `${deltas[i] || ''}${i === deltas.length - 1 ? '' : ' '}`,
|
|
187
|
+
...(i === deltas.length - 1 ? { name } : null),
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
],
|
|
179
191
|
},
|
|
180
192
|
};
|
|
181
193
|
}
|
|
@@ -215,7 +227,7 @@ class RunnerListener {
|
|
|
215
227
|
.on('finalFunctionCallResult', (result) => (this.finalFunctionCallResult = result))
|
|
216
228
|
.on('totalUsage', (usage) => (this.totalUsage = usage))
|
|
217
229
|
.on('error', (error) => (this.error = error))
|
|
218
|
-
.on('abort', () => (this.gotAbort = true))
|
|
230
|
+
.on('abort', (error) => ((this.error = error), (this.gotAbort = true)))
|
|
219
231
|
.on('end', () => (this.gotEnd = true))
|
|
220
232
|
.once('message', () => this.onceMessageCallCount++);
|
|
221
233
|
}
|
|
@@ -262,7 +274,7 @@ class RunnerListener {
|
|
|
262
274
|
.map((m) => m.content as string)
|
|
263
275
|
.filter(Boolean);
|
|
264
276
|
expect(this.contents).toEqual(expectedContents);
|
|
265
|
-
expect(this.finalMessage).toEqual(
|
|
277
|
+
expect(this.finalMessage).toEqual([...this.messages].reverse().find((x) => x.role === 'assistant'));
|
|
266
278
|
expect(await this.runner.finalMessage()).toEqual(this.finalMessage);
|
|
267
279
|
expect(this.finalContent).toEqual(expectedContents[expectedContents.length - 1] ?? null);
|
|
268
280
|
expect(await this.runner.finalContent()).toEqual(this.finalContent);
|
|
@@ -329,6 +341,7 @@ class StreamingRunnerListener {
|
|
|
329
341
|
.on('finalFunctionCall', (functionCall) => (this.finalFunctionCall = functionCall))
|
|
330
342
|
.on('finalFunctionCallResult', (result) => (this.finalFunctionCallResult = result))
|
|
331
343
|
.on('error', (error) => (this.error = error))
|
|
344
|
+
.on('abort', (abort) => (this.error = abort))
|
|
332
345
|
.on('end', () => (this.gotEnd = true));
|
|
333
346
|
}
|
|
334
347
|
|
|
@@ -365,7 +378,7 @@ class StreamingRunnerListener {
|
|
|
365
378
|
if (error) return;
|
|
366
379
|
|
|
367
380
|
if (this.eventContents.length) expect(this.eventChunks.length).toBeGreaterThan(0);
|
|
368
|
-
expect(this.finalMessage).toEqual(
|
|
381
|
+
expect(this.finalMessage).toEqual([...this.eventMessages].reverse().find((x) => x.role === 'assistant'));
|
|
369
382
|
expect(await this.runner.finalMessage()).toEqual(this.finalMessage);
|
|
370
383
|
expect(this.finalContent).toEqual(this.eventContents[this.eventContents.length - 1]?.[1] ?? null);
|
|
371
384
|
expect(await this.runner.finalContent()).toEqual(this.finalContent);
|
|
@@ -393,45 +406,54 @@ class StreamingRunnerListener {
|
|
|
393
406
|
function _typeTests() {
|
|
394
407
|
const openai = new OpenAI();
|
|
395
408
|
|
|
396
|
-
openai.beta.chat.completions.
|
|
409
|
+
openai.beta.chat.completions.runTools({
|
|
397
410
|
messages: [
|
|
398
411
|
{ role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
|
|
399
412
|
],
|
|
400
413
|
model: 'gpt-3.5-turbo',
|
|
401
|
-
|
|
414
|
+
tools: [
|
|
402
415
|
{
|
|
403
|
-
|
|
404
|
-
function:
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
416
|
+
type: 'function',
|
|
417
|
+
function: {
|
|
418
|
+
name: 'numProperties',
|
|
419
|
+
function: (obj: object) => String(Object.keys(obj).length),
|
|
420
|
+
parameters: { type: 'object' },
|
|
421
|
+
parse: (str: string): object => {
|
|
422
|
+
const result = JSON.parse(str);
|
|
423
|
+
if (!(result instanceof Object) || Array.isArray(result)) {
|
|
424
|
+
throw new Error('must be an object');
|
|
425
|
+
}
|
|
426
|
+
return result;
|
|
427
|
+
},
|
|
428
|
+
description: 'gets the number of properties on an object',
|
|
412
429
|
},
|
|
413
|
-
description: 'gets the number of properties on an object',
|
|
414
430
|
},
|
|
415
431
|
{
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
432
|
+
type: 'function',
|
|
433
|
+
function: {
|
|
434
|
+
function: (str: string) => String(str.length),
|
|
435
|
+
parameters: { type: 'string' },
|
|
436
|
+
description: 'gets the length of a string',
|
|
437
|
+
},
|
|
419
438
|
},
|
|
420
|
-
// @ts-expect-error function must accept string if parse is omitted
|
|
421
439
|
{
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
440
|
+
type: 'function',
|
|
441
|
+
// @ts-expect-error function must accept string if parse is omitted
|
|
442
|
+
function: {
|
|
443
|
+
function: (obj: object) => String(Object.keys(obj).length),
|
|
444
|
+
parameters: { type: 'object' },
|
|
445
|
+
description: 'gets the number of properties on an object',
|
|
446
|
+
},
|
|
425
447
|
},
|
|
426
448
|
],
|
|
427
449
|
});
|
|
428
|
-
openai.beta.chat.completions.
|
|
450
|
+
openai.beta.chat.completions.runTools({
|
|
429
451
|
messages: [
|
|
430
452
|
{ role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
|
|
431
453
|
],
|
|
432
454
|
model: 'gpt-3.5-turbo',
|
|
433
|
-
|
|
434
|
-
new
|
|
455
|
+
tools: [
|
|
456
|
+
new ParsingToolFunction({
|
|
435
457
|
name: 'numProperties',
|
|
436
458
|
// @ts-expect-error parse and function don't match
|
|
437
459
|
parse: (str: string) => str,
|
|
@@ -441,13 +463,13 @@ function _typeTests() {
|
|
|
441
463
|
}),
|
|
442
464
|
],
|
|
443
465
|
});
|
|
444
|
-
openai.beta.chat.completions.
|
|
466
|
+
openai.beta.chat.completions.runTools({
|
|
445
467
|
messages: [
|
|
446
468
|
{ role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
|
|
447
469
|
],
|
|
448
470
|
model: 'gpt-3.5-turbo',
|
|
449
|
-
|
|
450
|
-
new
|
|
471
|
+
tools: [
|
|
472
|
+
new ParsingToolFunction({
|
|
451
473
|
name: 'numProperties',
|
|
452
474
|
parse: (str: string): object => {
|
|
453
475
|
const result = JSON.parse(str);
|
|
@@ -460,7 +482,7 @@ function _typeTests() {
|
|
|
460
482
|
parameters: { type: 'object' },
|
|
461
483
|
description: 'gets the number of properties on an object',
|
|
462
484
|
}),
|
|
463
|
-
new
|
|
485
|
+
new ParsingToolFunction({
|
|
464
486
|
name: 'keys',
|
|
465
487
|
parse: (str: string): object => {
|
|
466
488
|
const result = JSON.parse(str);
|
|
@@ -473,7 +495,7 @@ function _typeTests() {
|
|
|
473
495
|
parameters: { type: 'object' },
|
|
474
496
|
description: 'gets the number of properties on an object',
|
|
475
497
|
}),
|
|
476
|
-
new
|
|
498
|
+
new ParsingToolFunction({
|
|
477
499
|
name: 'len2',
|
|
478
500
|
// @ts-expect-error parse and function don't match
|
|
479
501
|
parse: (str: string) => str,
|
|
@@ -483,140 +505,177 @@ function _typeTests() {
|
|
|
483
505
|
}),
|
|
484
506
|
],
|
|
485
507
|
});
|
|
486
|
-
openai.beta.chat.completions.
|
|
508
|
+
openai.beta.chat.completions.runTools({
|
|
487
509
|
messages: [
|
|
488
510
|
{ role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
|
|
489
511
|
],
|
|
490
512
|
model: 'gpt-3.5-turbo',
|
|
491
513
|
// @ts-ignore error occurs here in TS 4
|
|
492
|
-
|
|
514
|
+
tools: [
|
|
493
515
|
{
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
516
|
+
type: 'function',
|
|
517
|
+
function: {
|
|
518
|
+
name: 'numProperties',
|
|
519
|
+
parse: (str: string): object => {
|
|
520
|
+
const result = JSON.parse(str);
|
|
521
|
+
if (!(result instanceof Object) || Array.isArray(result)) {
|
|
522
|
+
throw new Error('must be an object');
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
525
|
+
},
|
|
526
|
+
function: (obj: object) => String(Object.keys(obj).length),
|
|
527
|
+
parameters: { type: 'object' },
|
|
528
|
+
description: 'gets the number of properties on an object',
|
|
501
529
|
},
|
|
502
|
-
function: (obj: object) => String(Object.keys(obj).length),
|
|
503
|
-
parameters: { type: 'object' },
|
|
504
|
-
description: 'gets the number of properties on an object',
|
|
505
530
|
},
|
|
506
531
|
{
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
532
|
+
type: 'function',
|
|
533
|
+
function: {
|
|
534
|
+
name: 'keys',
|
|
535
|
+
parse: (str: string): object => {
|
|
536
|
+
const result = JSON.parse(str);
|
|
537
|
+
if (!(result instanceof Object)) {
|
|
538
|
+
throw new Error('must be an Object');
|
|
539
|
+
}
|
|
540
|
+
return result;
|
|
541
|
+
},
|
|
542
|
+
function: (obj: object) => Object.keys(obj).join(', '),
|
|
543
|
+
parameters: { type: 'object' },
|
|
544
|
+
description: 'gets the number of properties on an object',
|
|
514
545
|
},
|
|
515
|
-
function: (obj: object) => Object.keys(obj).join(', '),
|
|
516
|
-
parameters: { type: 'object' },
|
|
517
|
-
description: 'gets the number of properties on an object',
|
|
518
546
|
},
|
|
519
547
|
{
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
548
|
+
type: 'function',
|
|
549
|
+
function: {
|
|
550
|
+
name: 'len2',
|
|
551
|
+
parse: (str: string) => str,
|
|
552
|
+
// @ts-ignore error occurs here in TS 5
|
|
553
|
+
// function input doesn't match parse output
|
|
554
|
+
function: (obj: object) => String(Object.keys(obj).length),
|
|
555
|
+
parameters: { type: 'object' },
|
|
556
|
+
description: 'gets the number of properties on an object',
|
|
557
|
+
},
|
|
527
558
|
},
|
|
528
559
|
] as const,
|
|
529
560
|
});
|
|
530
561
|
}
|
|
531
562
|
|
|
532
563
|
describe('resource completions', () => {
|
|
533
|
-
|
|
534
|
-
describe.skip('runFunctions with stream: false', () => {
|
|
564
|
+
describe('runTools with stream: false', () => {
|
|
535
565
|
test('successful flow', async () => {
|
|
536
566
|
const { fetch, handleRequest } = mockChatCompletionFetch();
|
|
537
567
|
|
|
538
568
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
539
569
|
|
|
540
|
-
const runner = openai.beta.chat.completions.
|
|
570
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
541
571
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
542
572
|
model: 'gpt-3.5-turbo',
|
|
543
|
-
|
|
573
|
+
tools: [
|
|
544
574
|
{
|
|
545
|
-
|
|
546
|
-
|
|
575
|
+
type: 'function',
|
|
576
|
+
function: {
|
|
577
|
+
function: function getWeather() {
|
|
578
|
+
return `it's raining`;
|
|
579
|
+
},
|
|
580
|
+
parameters: {},
|
|
581
|
+
description: 'gets the weather',
|
|
547
582
|
},
|
|
548
|
-
parameters: {},
|
|
549
|
-
description: 'gets the weather',
|
|
550
583
|
},
|
|
551
584
|
],
|
|
552
585
|
});
|
|
553
586
|
const listener = new RunnerListener(runner);
|
|
554
587
|
|
|
555
|
-
await
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
choices: [
|
|
561
|
-
{
|
|
562
|
-
index: 0,
|
|
563
|
-
finish_reason: 'function_call',
|
|
564
|
-
message: {
|
|
565
|
-
role: 'assistant',
|
|
566
|
-
content: null,
|
|
567
|
-
function_call: {
|
|
568
|
-
arguments: '',
|
|
569
|
-
name: 'getWeather',
|
|
570
|
-
},
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
],
|
|
574
|
-
created: Math.floor(Date.now() / 1000),
|
|
575
|
-
model: 'gpt-3.5-turbo',
|
|
576
|
-
object: 'chat.completion',
|
|
577
|
-
};
|
|
578
|
-
}),
|
|
579
|
-
handleRequest(async (request) => {
|
|
580
|
-
expect(request.messages).toEqual([
|
|
581
|
-
{ role: 'user', content: 'tell me what the weather is like' },
|
|
588
|
+
await handleRequest(async (request) => {
|
|
589
|
+
expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
|
|
590
|
+
return {
|
|
591
|
+
id: '1',
|
|
592
|
+
choices: [
|
|
582
593
|
{
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
594
|
+
index: 0,
|
|
595
|
+
finish_reason: 'function_call',
|
|
596
|
+
message: {
|
|
597
|
+
role: 'assistant',
|
|
598
|
+
content: null,
|
|
599
|
+
tool_calls: [
|
|
600
|
+
{
|
|
601
|
+
type: 'function',
|
|
602
|
+
id: '123',
|
|
603
|
+
function: {
|
|
604
|
+
arguments: '',
|
|
605
|
+
name: 'getWeather',
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
],
|
|
588
609
|
},
|
|
589
610
|
},
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
611
|
+
],
|
|
612
|
+
created: Math.floor(Date.now() / 1000),
|
|
613
|
+
model: 'gpt-3.5-turbo',
|
|
614
|
+
object: 'chat.completion',
|
|
615
|
+
};
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
await handleRequest(async (request) => {
|
|
619
|
+
expect(request.messages).toEqual([
|
|
620
|
+
{ role: 'user', content: 'tell me what the weather is like' },
|
|
621
|
+
{
|
|
622
|
+
role: 'assistant',
|
|
623
|
+
content: null,
|
|
624
|
+
tool_calls: [
|
|
599
625
|
{
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
626
|
+
type: 'function',
|
|
627
|
+
id: '123',
|
|
628
|
+
function: {
|
|
629
|
+
arguments: '',
|
|
630
|
+
name: 'getWeather',
|
|
605
631
|
},
|
|
606
632
|
},
|
|
607
633
|
],
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
role: 'tool',
|
|
637
|
+
content: `it's raining`,
|
|
638
|
+
tool_call_id: '123',
|
|
639
|
+
},
|
|
640
|
+
]);
|
|
641
|
+
|
|
642
|
+
return {
|
|
643
|
+
id: '2',
|
|
644
|
+
choices: [
|
|
645
|
+
{
|
|
646
|
+
index: 0,
|
|
647
|
+
finish_reason: 'stop',
|
|
648
|
+
message: {
|
|
649
|
+
role: 'assistant',
|
|
650
|
+
content: `it's raining`,
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
],
|
|
654
|
+
created: Math.floor(Date.now() / 1000),
|
|
655
|
+
model: 'gpt-3.5-turbo',
|
|
656
|
+
object: 'chat.completion',
|
|
657
|
+
};
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
await runner.done();
|
|
615
661
|
|
|
616
662
|
expect(listener.messages).toEqual([
|
|
617
663
|
{ role: 'user', content: 'tell me what the weather is like' },
|
|
618
|
-
{
|
|
619
|
-
|
|
664
|
+
{
|
|
665
|
+
role: 'assistant',
|
|
666
|
+
content: null,
|
|
667
|
+
tool_calls: [
|
|
668
|
+
{
|
|
669
|
+
type: 'function',
|
|
670
|
+
id: '123',
|
|
671
|
+
function: {
|
|
672
|
+
arguments: '',
|
|
673
|
+
name: 'getWeather',
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
],
|
|
677
|
+
},
|
|
678
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '123' },
|
|
620
679
|
{ role: 'assistant', content: "it's raining" },
|
|
621
680
|
]);
|
|
622
681
|
expect(listener.functionCallResults).toEqual([`it's raining`]);
|
|
@@ -628,17 +687,20 @@ describe('resource completions', () => {
|
|
|
628
687
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
629
688
|
|
|
630
689
|
const controller = new AbortController();
|
|
631
|
-
const runner = openai.beta.chat.completions.
|
|
690
|
+
const runner = openai.beta.chat.completions.runTools(
|
|
632
691
|
{
|
|
633
692
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
634
693
|
model: 'gpt-3.5-turbo',
|
|
635
|
-
|
|
694
|
+
tools: [
|
|
636
695
|
{
|
|
637
|
-
|
|
638
|
-
|
|
696
|
+
type: 'function',
|
|
697
|
+
function: {
|
|
698
|
+
function: function getWeather() {
|
|
699
|
+
return `it's raining`;
|
|
700
|
+
},
|
|
701
|
+
parameters: {},
|
|
702
|
+
description: 'gets the weather',
|
|
639
703
|
},
|
|
640
|
-
parameters: {},
|
|
641
|
-
description: 'gets the weather',
|
|
642
704
|
},
|
|
643
705
|
],
|
|
644
706
|
},
|
|
@@ -657,10 +719,16 @@ describe('resource completions', () => {
|
|
|
657
719
|
message: {
|
|
658
720
|
role: 'assistant',
|
|
659
721
|
content: null,
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
722
|
+
tool_calls: [
|
|
723
|
+
{
|
|
724
|
+
type: 'function',
|
|
725
|
+
id: '123',
|
|
726
|
+
function: {
|
|
727
|
+
arguments: '',
|
|
728
|
+
name: 'getWeather',
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
],
|
|
664
732
|
},
|
|
665
733
|
},
|
|
666
734
|
],
|
|
@@ -676,8 +744,21 @@ describe('resource completions', () => {
|
|
|
676
744
|
|
|
677
745
|
expect(listener.messages).toEqual([
|
|
678
746
|
{ role: 'user', content: 'tell me what the weather is like' },
|
|
679
|
-
{
|
|
680
|
-
|
|
747
|
+
{
|
|
748
|
+
role: 'assistant',
|
|
749
|
+
content: null,
|
|
750
|
+
tool_calls: [
|
|
751
|
+
{
|
|
752
|
+
type: 'function',
|
|
753
|
+
id: '123',
|
|
754
|
+
function: {
|
|
755
|
+
arguments: '',
|
|
756
|
+
name: 'getWeather',
|
|
757
|
+
},
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
},
|
|
761
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '123' },
|
|
681
762
|
]);
|
|
682
763
|
expect(listener.functionCallResults).toEqual([`it's raining`]);
|
|
683
764
|
await listener.sanityCheck({ error: 'Request was aborted.' });
|
|
@@ -688,7 +769,7 @@ describe('resource completions', () => {
|
|
|
688
769
|
|
|
689
770
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
690
771
|
|
|
691
|
-
const runner = openai.beta.chat.completions.
|
|
772
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
692
773
|
messages: [
|
|
693
774
|
{
|
|
694
775
|
role: 'user',
|
|
@@ -696,8 +777,8 @@ describe('resource completions', () => {
|
|
|
696
777
|
},
|
|
697
778
|
],
|
|
698
779
|
model: 'gpt-3.5-turbo',
|
|
699
|
-
|
|
700
|
-
new
|
|
780
|
+
tools: [
|
|
781
|
+
new ParsingToolFunction({
|
|
701
782
|
name: 'numProperties',
|
|
702
783
|
function: (obj: object) => String(Object.keys(obj).length),
|
|
703
784
|
parameters: { type: 'object' },
|
|
@@ -714,86 +795,96 @@ describe('resource completions', () => {
|
|
|
714
795
|
});
|
|
715
796
|
const listener = new RunnerListener(runner);
|
|
716
797
|
|
|
717
|
-
await
|
|
718
|
-
|
|
719
|
-
|
|
798
|
+
await handleRequest(async (request) => {
|
|
799
|
+
expect(request.messages).toEqual([
|
|
800
|
+
{
|
|
801
|
+
role: 'user',
|
|
802
|
+
content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
|
|
803
|
+
},
|
|
804
|
+
]);
|
|
805
|
+
return {
|
|
806
|
+
id: '1',
|
|
807
|
+
choices: [
|
|
720
808
|
{
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
function_call: {
|
|
735
|
-
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
736
|
-
name: 'numProperties',
|
|
809
|
+
index: 0,
|
|
810
|
+
finish_reason: 'function_call',
|
|
811
|
+
message: {
|
|
812
|
+
role: 'assistant',
|
|
813
|
+
content: null,
|
|
814
|
+
tool_calls: [
|
|
815
|
+
{
|
|
816
|
+
type: 'function',
|
|
817
|
+
id: '123',
|
|
818
|
+
function: {
|
|
819
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
820
|
+
name: 'numProperties',
|
|
821
|
+
},
|
|
737
822
|
},
|
|
738
|
-
|
|
823
|
+
],
|
|
739
824
|
},
|
|
740
|
-
],
|
|
741
|
-
created: Math.floor(Date.now() / 1000),
|
|
742
|
-
model: 'gpt-3.5-turbo',
|
|
743
|
-
object: 'chat.completion',
|
|
744
|
-
usage: {
|
|
745
|
-
completion_tokens: 5,
|
|
746
|
-
prompt_tokens: 20,
|
|
747
|
-
total_tokens: 25,
|
|
748
825
|
},
|
|
749
|
-
|
|
750
|
-
|
|
826
|
+
],
|
|
827
|
+
created: Math.floor(Date.now() / 1000),
|
|
828
|
+
model: 'gpt-3.5-turbo',
|
|
829
|
+
object: 'chat.completion',
|
|
830
|
+
usage: {
|
|
831
|
+
completion_tokens: 5,
|
|
832
|
+
prompt_tokens: 20,
|
|
833
|
+
total_tokens: 25,
|
|
834
|
+
},
|
|
835
|
+
};
|
|
836
|
+
});
|
|
751
837
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
763
|
-
name: 'numProperties',
|
|
764
|
-
},
|
|
765
|
-
},
|
|
766
|
-
{
|
|
767
|
-
role: 'function',
|
|
768
|
-
content: '3',
|
|
769
|
-
name: 'numProperties',
|
|
770
|
-
},
|
|
771
|
-
]);
|
|
772
|
-
return {
|
|
773
|
-
id: '2',
|
|
774
|
-
choices: [
|
|
838
|
+
await handleRequest(async (request) => {
|
|
839
|
+
expect(request.messages).toEqual([
|
|
840
|
+
{
|
|
841
|
+
role: 'user',
|
|
842
|
+
content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
role: 'assistant',
|
|
846
|
+
content: null,
|
|
847
|
+
tool_calls: [
|
|
775
848
|
{
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
849
|
+
type: 'function',
|
|
850
|
+
id: '123',
|
|
851
|
+
function: {
|
|
852
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
853
|
+
name: 'numProperties',
|
|
781
854
|
},
|
|
782
855
|
},
|
|
783
856
|
],
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
role: 'tool',
|
|
860
|
+
content: '3',
|
|
861
|
+
tool_call_id: '123',
|
|
862
|
+
},
|
|
863
|
+
]);
|
|
864
|
+
return {
|
|
865
|
+
id: '2',
|
|
866
|
+
choices: [
|
|
867
|
+
{
|
|
868
|
+
index: 0,
|
|
869
|
+
finish_reason: 'stop',
|
|
870
|
+
message: {
|
|
871
|
+
role: 'assistant',
|
|
872
|
+
content: `there are 3 properties in {"a": 1, "b": 2, "c": 3}`,
|
|
873
|
+
},
|
|
791
874
|
},
|
|
792
|
-
|
|
793
|
-
|
|
875
|
+
],
|
|
876
|
+
created: Math.floor(Date.now() / 1000),
|
|
877
|
+
model: 'gpt-3.5-turbo',
|
|
878
|
+
object: 'chat.completion',
|
|
879
|
+
usage: {
|
|
880
|
+
completion_tokens: 10,
|
|
881
|
+
prompt_tokens: 25,
|
|
882
|
+
total_tokens: 35,
|
|
883
|
+
},
|
|
884
|
+
};
|
|
885
|
+
});
|
|
794
886
|
|
|
795
|
-
|
|
796
|
-
]);
|
|
887
|
+
await runner.done();
|
|
797
888
|
|
|
798
889
|
expect(listener.messages).toEqual([
|
|
799
890
|
{
|
|
@@ -803,9 +894,15 @@ describe('resource completions', () => {
|
|
|
803
894
|
{
|
|
804
895
|
role: 'assistant',
|
|
805
896
|
content: null,
|
|
806
|
-
|
|
897
|
+
tool_calls: [
|
|
898
|
+
{
|
|
899
|
+
type: 'function',
|
|
900
|
+
id: '123',
|
|
901
|
+
function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
|
|
902
|
+
},
|
|
903
|
+
],
|
|
807
904
|
},
|
|
808
|
-
{ role: '
|
|
905
|
+
{ role: 'tool', content: '3', tool_call_id: '123' },
|
|
809
906
|
{ role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
|
|
810
907
|
]);
|
|
811
908
|
expect(listener.functionCallResults).toEqual(['3']);
|
|
@@ -816,7 +913,7 @@ describe('resource completions', () => {
|
|
|
816
913
|
|
|
817
914
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
818
915
|
|
|
819
|
-
const runner = openai.beta.chat.completions.
|
|
916
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
820
917
|
messages: [
|
|
821
918
|
{
|
|
822
919
|
role: 'user',
|
|
@@ -824,8 +921,8 @@ describe('resource completions', () => {
|
|
|
824
921
|
},
|
|
825
922
|
],
|
|
826
923
|
model: 'gpt-3.5-turbo',
|
|
827
|
-
|
|
828
|
-
new
|
|
924
|
+
tools: [
|
|
925
|
+
new ParsingToolFunction({
|
|
829
926
|
name: 'numProperties',
|
|
830
927
|
function: (obj: object) => String(Object.keys(obj).length),
|
|
831
928
|
parameters: { type: 'object' },
|
|
@@ -859,10 +956,16 @@ describe('resource completions', () => {
|
|
|
859
956
|
message: {
|
|
860
957
|
role: 'assistant',
|
|
861
958
|
content: null,
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
959
|
+
tool_calls: [
|
|
960
|
+
{
|
|
961
|
+
type: 'function',
|
|
962
|
+
id: '123',
|
|
963
|
+
function: {
|
|
964
|
+
arguments: '[{"a": 1, "b": 2, "c": 3}]',
|
|
965
|
+
name: 'numProperties',
|
|
966
|
+
},
|
|
967
|
+
},
|
|
968
|
+
],
|
|
866
969
|
},
|
|
867
970
|
},
|
|
868
971
|
],
|
|
@@ -880,15 +983,21 @@ describe('resource completions', () => {
|
|
|
880
983
|
{
|
|
881
984
|
role: 'assistant',
|
|
882
985
|
content: null,
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
986
|
+
tool_calls: [
|
|
987
|
+
{
|
|
988
|
+
type: 'function',
|
|
989
|
+
id: '123',
|
|
990
|
+
function: {
|
|
991
|
+
arguments: '[{"a": 1, "b": 2, "c": 3}]',
|
|
992
|
+
name: 'numProperties',
|
|
993
|
+
},
|
|
994
|
+
},
|
|
995
|
+
],
|
|
887
996
|
},
|
|
888
997
|
{
|
|
889
|
-
role: '
|
|
998
|
+
role: 'tool',
|
|
890
999
|
content: `must be an object`,
|
|
891
|
-
|
|
1000
|
+
tool_call_id: '123',
|
|
892
1001
|
},
|
|
893
1002
|
]);
|
|
894
1003
|
return {
|
|
@@ -900,10 +1009,16 @@ describe('resource completions', () => {
|
|
|
900
1009
|
message: {
|
|
901
1010
|
role: 'assistant',
|
|
902
1011
|
content: null,
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1012
|
+
tool_calls: [
|
|
1013
|
+
{
|
|
1014
|
+
type: 'function',
|
|
1015
|
+
id: '1234',
|
|
1016
|
+
function: {
|
|
1017
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
1018
|
+
name: 'numProperties',
|
|
1019
|
+
},
|
|
1020
|
+
},
|
|
1021
|
+
],
|
|
907
1022
|
},
|
|
908
1023
|
},
|
|
909
1024
|
],
|
|
@@ -921,28 +1036,40 @@ describe('resource completions', () => {
|
|
|
921
1036
|
{
|
|
922
1037
|
role: 'assistant',
|
|
923
1038
|
content: null,
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1039
|
+
tool_calls: [
|
|
1040
|
+
{
|
|
1041
|
+
type: 'function',
|
|
1042
|
+
id: '123',
|
|
1043
|
+
function: {
|
|
1044
|
+
arguments: '[{"a": 1, "b": 2, "c": 3}]',
|
|
1045
|
+
name: 'numProperties',
|
|
1046
|
+
},
|
|
1047
|
+
},
|
|
1048
|
+
],
|
|
928
1049
|
},
|
|
929
1050
|
{
|
|
930
|
-
role: '
|
|
1051
|
+
role: 'tool',
|
|
931
1052
|
content: `must be an object`,
|
|
932
|
-
|
|
1053
|
+
tool_call_id: '123',
|
|
933
1054
|
},
|
|
934
1055
|
{
|
|
935
1056
|
role: 'assistant',
|
|
936
1057
|
content: null,
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1058
|
+
tool_calls: [
|
|
1059
|
+
{
|
|
1060
|
+
type: 'function',
|
|
1061
|
+
id: '1234',
|
|
1062
|
+
function: {
|
|
1063
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
1064
|
+
name: 'numProperties',
|
|
1065
|
+
},
|
|
1066
|
+
},
|
|
1067
|
+
],
|
|
941
1068
|
},
|
|
942
1069
|
{
|
|
943
|
-
role: '
|
|
1070
|
+
role: 'tool',
|
|
944
1071
|
content: '3',
|
|
945
|
-
|
|
1072
|
+
tool_call_id: '1234',
|
|
946
1073
|
},
|
|
947
1074
|
]);
|
|
948
1075
|
return {
|
|
@@ -973,15 +1100,27 @@ describe('resource completions', () => {
|
|
|
973
1100
|
{
|
|
974
1101
|
role: 'assistant',
|
|
975
1102
|
content: null,
|
|
976
|
-
|
|
1103
|
+
tool_calls: [
|
|
1104
|
+
{
|
|
1105
|
+
type: 'function',
|
|
1106
|
+
id: '123',
|
|
1107
|
+
function: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
|
|
1108
|
+
},
|
|
1109
|
+
],
|
|
977
1110
|
},
|
|
978
|
-
{ role: '
|
|
1111
|
+
{ role: 'tool', content: `must be an object`, tool_call_id: '123' },
|
|
979
1112
|
{
|
|
980
1113
|
role: 'assistant',
|
|
981
1114
|
content: null,
|
|
982
|
-
|
|
1115
|
+
tool_calls: [
|
|
1116
|
+
{
|
|
1117
|
+
type: 'function',
|
|
1118
|
+
id: '1234',
|
|
1119
|
+
function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
|
|
1120
|
+
},
|
|
1121
|
+
],
|
|
983
1122
|
},
|
|
984
|
-
{ role: '
|
|
1123
|
+
{ role: 'tool', content: '3', tool_call_id: '1234' },
|
|
985
1124
|
{ role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
|
|
986
1125
|
]);
|
|
987
1126
|
expect(listener.functionCallResults).toEqual([`must be an object`, '3']);
|
|
@@ -992,19 +1131,25 @@ describe('resource completions', () => {
|
|
|
992
1131
|
|
|
993
1132
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
994
1133
|
|
|
995
|
-
const runner = openai.beta.chat.completions.
|
|
1134
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
996
1135
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
997
1136
|
model: 'gpt-3.5-turbo',
|
|
998
|
-
|
|
999
|
-
|
|
1137
|
+
tool_choice: {
|
|
1138
|
+
type: 'function',
|
|
1139
|
+
function: {
|
|
1140
|
+
name: 'getWeather',
|
|
1141
|
+
},
|
|
1000
1142
|
},
|
|
1001
|
-
|
|
1143
|
+
tools: [
|
|
1002
1144
|
{
|
|
1003
|
-
|
|
1004
|
-
|
|
1145
|
+
type: 'function',
|
|
1146
|
+
function: {
|
|
1147
|
+
function: function getWeather() {
|
|
1148
|
+
return `it's raining`;
|
|
1149
|
+
},
|
|
1150
|
+
parameters: {},
|
|
1151
|
+
description: 'gets the weather',
|
|
1005
1152
|
},
|
|
1006
|
-
parameters: {},
|
|
1007
|
-
description: 'gets the weather',
|
|
1008
1153
|
},
|
|
1009
1154
|
],
|
|
1010
1155
|
});
|
|
@@ -1022,10 +1167,16 @@ describe('resource completions', () => {
|
|
|
1022
1167
|
message: {
|
|
1023
1168
|
role: 'assistant',
|
|
1024
1169
|
content: null,
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1170
|
+
tool_calls: [
|
|
1171
|
+
{
|
|
1172
|
+
type: 'function',
|
|
1173
|
+
id: '123',
|
|
1174
|
+
function: {
|
|
1175
|
+
arguments: '',
|
|
1176
|
+
name: 'getWeather',
|
|
1177
|
+
},
|
|
1178
|
+
},
|
|
1179
|
+
],
|
|
1029
1180
|
},
|
|
1030
1181
|
},
|
|
1031
1182
|
],
|
|
@@ -1039,8 +1190,21 @@ describe('resource completions', () => {
|
|
|
1039
1190
|
|
|
1040
1191
|
expect(listener.messages).toEqual([
|
|
1041
1192
|
{ role: 'user', content: 'tell me what the weather is like' },
|
|
1042
|
-
{
|
|
1043
|
-
|
|
1193
|
+
{
|
|
1194
|
+
role: 'assistant',
|
|
1195
|
+
content: null,
|
|
1196
|
+
tool_calls: [
|
|
1197
|
+
{
|
|
1198
|
+
type: 'function',
|
|
1199
|
+
id: '123',
|
|
1200
|
+
function: {
|
|
1201
|
+
arguments: '',
|
|
1202
|
+
name: 'getWeather',
|
|
1203
|
+
},
|
|
1204
|
+
},
|
|
1205
|
+
],
|
|
1206
|
+
},
|
|
1207
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '123' },
|
|
1044
1208
|
]);
|
|
1045
1209
|
expect(listener.functionCallResults).toEqual([`it's raining`]);
|
|
1046
1210
|
await listener.sanityCheck();
|
|
@@ -1050,16 +1214,19 @@ describe('resource completions', () => {
|
|
|
1050
1214
|
|
|
1051
1215
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1052
1216
|
|
|
1053
|
-
const runner = openai.beta.chat.completions.
|
|
1217
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1054
1218
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1055
1219
|
model: 'gpt-3.5-turbo',
|
|
1056
|
-
|
|
1220
|
+
tools: [
|
|
1057
1221
|
{
|
|
1058
|
-
|
|
1059
|
-
|
|
1222
|
+
type: 'function',
|
|
1223
|
+
function: {
|
|
1224
|
+
function: function getWeather() {
|
|
1225
|
+
return `it's raining`;
|
|
1226
|
+
},
|
|
1227
|
+
parameters: {},
|
|
1228
|
+
description: 'gets the weather',
|
|
1060
1229
|
},
|
|
1061
|
-
parameters: {},
|
|
1062
|
-
description: 'gets the weather',
|
|
1063
1230
|
},
|
|
1064
1231
|
],
|
|
1065
1232
|
});
|
|
@@ -1077,10 +1244,16 @@ describe('resource completions', () => {
|
|
|
1077
1244
|
message: {
|
|
1078
1245
|
role: 'assistant',
|
|
1079
1246
|
content: null,
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1247
|
+
tool_calls: [
|
|
1248
|
+
{
|
|
1249
|
+
type: 'function',
|
|
1250
|
+
id: '123',
|
|
1251
|
+
function: {
|
|
1252
|
+
arguments: '',
|
|
1253
|
+
name: 'get_weather',
|
|
1254
|
+
},
|
|
1255
|
+
},
|
|
1256
|
+
],
|
|
1084
1257
|
},
|
|
1085
1258
|
},
|
|
1086
1259
|
],
|
|
@@ -1095,15 +1268,21 @@ describe('resource completions', () => {
|
|
|
1095
1268
|
{
|
|
1096
1269
|
role: 'assistant',
|
|
1097
1270
|
content: null,
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1271
|
+
tool_calls: [
|
|
1272
|
+
{
|
|
1273
|
+
type: 'function',
|
|
1274
|
+
id: '123',
|
|
1275
|
+
function: {
|
|
1276
|
+
arguments: '',
|
|
1277
|
+
name: 'get_weather',
|
|
1278
|
+
},
|
|
1279
|
+
},
|
|
1280
|
+
],
|
|
1102
1281
|
},
|
|
1103
1282
|
{
|
|
1104
|
-
role: '
|
|
1105
|
-
content: `Invalid
|
|
1106
|
-
|
|
1283
|
+
role: 'tool',
|
|
1284
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1285
|
+
tool_call_id: '123',
|
|
1107
1286
|
},
|
|
1108
1287
|
]);
|
|
1109
1288
|
return {
|
|
@@ -1115,10 +1294,16 @@ describe('resource completions', () => {
|
|
|
1115
1294
|
message: {
|
|
1116
1295
|
role: 'assistant',
|
|
1117
1296
|
content: null,
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1297
|
+
tool_calls: [
|
|
1298
|
+
{
|
|
1299
|
+
type: 'function',
|
|
1300
|
+
id: '1234',
|
|
1301
|
+
function: {
|
|
1302
|
+
arguments: '',
|
|
1303
|
+
name: 'getWeather',
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
],
|
|
1122
1307
|
},
|
|
1123
1308
|
},
|
|
1124
1309
|
],
|
|
@@ -1133,28 +1318,40 @@ describe('resource completions', () => {
|
|
|
1133
1318
|
{
|
|
1134
1319
|
role: 'assistant',
|
|
1135
1320
|
content: null,
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1321
|
+
tool_calls: [
|
|
1322
|
+
{
|
|
1323
|
+
type: 'function',
|
|
1324
|
+
id: '123',
|
|
1325
|
+
function: {
|
|
1326
|
+
arguments: '',
|
|
1327
|
+
name: 'get_weather',
|
|
1328
|
+
},
|
|
1329
|
+
},
|
|
1330
|
+
],
|
|
1140
1331
|
},
|
|
1141
1332
|
{
|
|
1142
|
-
role: '
|
|
1143
|
-
content: `Invalid
|
|
1144
|
-
|
|
1333
|
+
role: 'tool',
|
|
1334
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1335
|
+
tool_call_id: '123',
|
|
1145
1336
|
},
|
|
1146
1337
|
{
|
|
1147
1338
|
role: 'assistant',
|
|
1148
|
-
content: null,
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1339
|
+
content: null,
|
|
1340
|
+
tool_calls: [
|
|
1341
|
+
{
|
|
1342
|
+
type: 'function',
|
|
1343
|
+
id: '1234',
|
|
1344
|
+
function: {
|
|
1345
|
+
arguments: '',
|
|
1346
|
+
name: 'getWeather',
|
|
1347
|
+
},
|
|
1348
|
+
},
|
|
1349
|
+
],
|
|
1153
1350
|
},
|
|
1154
1351
|
{
|
|
1155
|
-
role: '
|
|
1352
|
+
role: 'tool',
|
|
1156
1353
|
content: `it's raining`,
|
|
1157
|
-
|
|
1354
|
+
tool_call_id: '1234',
|
|
1158
1355
|
},
|
|
1159
1356
|
]);
|
|
1160
1357
|
return {
|
|
@@ -1179,106 +1376,52 @@ describe('resource completions', () => {
|
|
|
1179
1376
|
|
|
1180
1377
|
expect(listener.messages).toEqual([
|
|
1181
1378
|
{ role: 'user', content: 'tell me what the weather is like' },
|
|
1182
|
-
{ role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
|
|
1183
1379
|
{
|
|
1184
|
-
role: '
|
|
1185
|
-
content:
|
|
1186
|
-
name: 'get_weather',
|
|
1380
|
+
role: 'assistant',
|
|
1381
|
+
content: null,
|
|
1382
|
+
tool_calls: [{ type: 'function', id: '123', function: { name: 'get_weather', arguments: '' } }],
|
|
1187
1383
|
},
|
|
1188
|
-
{
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
expect(listener.functionCallResults).toEqual([
|
|
1193
|
-
`Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1194
|
-
`it's raining`,
|
|
1195
|
-
]);
|
|
1196
|
-
await listener.sanityCheck();
|
|
1197
|
-
});
|
|
1198
|
-
test('wrong function name with single function call', async () => {
|
|
1199
|
-
const { fetch, handleRequest } = mockChatCompletionFetch();
|
|
1200
|
-
|
|
1201
|
-
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1202
|
-
|
|
1203
|
-
const runner = openai.beta.chat.completions.runFunctions({
|
|
1204
|
-
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1205
|
-
model: 'gpt-3.5-turbo',
|
|
1206
|
-
function_call: {
|
|
1207
|
-
name: 'getWeather',
|
|
1384
|
+
{
|
|
1385
|
+
role: 'tool',
|
|
1386
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1387
|
+
tool_call_id: '123',
|
|
1208
1388
|
},
|
|
1209
|
-
functions: [
|
|
1210
|
-
{
|
|
1211
|
-
function: function getWeather() {
|
|
1212
|
-
return `it's raining`;
|
|
1213
|
-
},
|
|
1214
|
-
parameters: {},
|
|
1215
|
-
description: 'gets the weather',
|
|
1216
|
-
},
|
|
1217
|
-
],
|
|
1218
|
-
});
|
|
1219
|
-
const listener = new RunnerListener(runner);
|
|
1220
|
-
|
|
1221
|
-
await Promise.all([
|
|
1222
|
-
handleRequest(async (request) => {
|
|
1223
|
-
expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
|
|
1224
|
-
return {
|
|
1225
|
-
id: '1',
|
|
1226
|
-
choices: [
|
|
1227
|
-
{
|
|
1228
|
-
index: 0,
|
|
1229
|
-
finish_reason: 'function_call',
|
|
1230
|
-
message: {
|
|
1231
|
-
role: 'assistant',
|
|
1232
|
-
content: null,
|
|
1233
|
-
function_call: {
|
|
1234
|
-
arguments: '',
|
|
1235
|
-
name: 'get_weather',
|
|
1236
|
-
},
|
|
1237
|
-
},
|
|
1238
|
-
},
|
|
1239
|
-
],
|
|
1240
|
-
created: Math.floor(Date.now() / 1000),
|
|
1241
|
-
model: 'gpt-3.5-turbo',
|
|
1242
|
-
object: 'chat.completion',
|
|
1243
|
-
};
|
|
1244
|
-
}),
|
|
1245
|
-
runner.done(),
|
|
1246
|
-
]);
|
|
1247
|
-
|
|
1248
|
-
expect(listener.messages).toEqual([
|
|
1249
|
-
{ role: 'user', content: 'tell me what the weather is like' },
|
|
1250
|
-
{ role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
|
|
1251
1389
|
{
|
|
1252
|
-
role: '
|
|
1253
|
-
content:
|
|
1254
|
-
name: '
|
|
1390
|
+
role: 'assistant',
|
|
1391
|
+
content: null,
|
|
1392
|
+
tool_calls: [{ type: 'function', id: '1234', function: { name: 'getWeather', arguments: '' } }],
|
|
1255
1393
|
},
|
|
1394
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '1234' },
|
|
1395
|
+
{ role: 'assistant', content: "it's raining" },
|
|
1256
1396
|
]);
|
|
1257
1397
|
expect(listener.functionCallResults).toEqual([
|
|
1258
|
-
`Invalid
|
|
1398
|
+
`Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1399
|
+
`it's raining`,
|
|
1259
1400
|
]);
|
|
1260
1401
|
await listener.sanityCheck();
|
|
1261
1402
|
});
|
|
1262
1403
|
});
|
|
1263
1404
|
|
|
1264
|
-
|
|
1265
|
-
describe.skip('runFunctions with stream: true', () => {
|
|
1405
|
+
describe('runTools with stream: true', () => {
|
|
1266
1406
|
test('successful flow', async () => {
|
|
1267
1407
|
const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
|
|
1268
1408
|
|
|
1269
1409
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1270
1410
|
|
|
1271
|
-
const runner = openai.beta.chat.completions.
|
|
1411
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1272
1412
|
stream: true,
|
|
1273
1413
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1274
1414
|
model: 'gpt-3.5-turbo',
|
|
1275
|
-
|
|
1415
|
+
tools: [
|
|
1276
1416
|
{
|
|
1277
|
-
|
|
1278
|
-
|
|
1417
|
+
type: 'function',
|
|
1418
|
+
function: {
|
|
1419
|
+
function: function getWeather() {
|
|
1420
|
+
return `it's raining`;
|
|
1421
|
+
},
|
|
1422
|
+
parameters: {},
|
|
1423
|
+
description: 'gets the weather',
|
|
1279
1424
|
},
|
|
1280
|
-
parameters: {},
|
|
1281
|
-
description: 'gets the weather',
|
|
1282
1425
|
},
|
|
1283
1426
|
],
|
|
1284
1427
|
});
|
|
@@ -1296,10 +1439,17 @@ describe('resource completions', () => {
|
|
|
1296
1439
|
delta: {
|
|
1297
1440
|
role: 'assistant',
|
|
1298
1441
|
content: null,
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1442
|
+
tool_calls: [
|
|
1443
|
+
{
|
|
1444
|
+
type: 'function',
|
|
1445
|
+
index: 0,
|
|
1446
|
+
id: '123',
|
|
1447
|
+
function: {
|
|
1448
|
+
arguments: '',
|
|
1449
|
+
name: 'getWeather',
|
|
1450
|
+
},
|
|
1451
|
+
},
|
|
1452
|
+
],
|
|
1303
1453
|
},
|
|
1304
1454
|
},
|
|
1305
1455
|
],
|
|
@@ -1314,15 +1464,21 @@ describe('resource completions', () => {
|
|
|
1314
1464
|
{
|
|
1315
1465
|
role: 'assistant',
|
|
1316
1466
|
content: null,
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1467
|
+
tool_calls: [
|
|
1468
|
+
{
|
|
1469
|
+
type: 'function',
|
|
1470
|
+
id: '123',
|
|
1471
|
+
function: {
|
|
1472
|
+
arguments: '',
|
|
1473
|
+
name: 'getWeather',
|
|
1474
|
+
},
|
|
1475
|
+
},
|
|
1476
|
+
],
|
|
1321
1477
|
},
|
|
1322
1478
|
{
|
|
1323
|
-
role: '
|
|
1479
|
+
role: 'tool',
|
|
1324
1480
|
content: `it's raining`,
|
|
1325
|
-
|
|
1481
|
+
tool_call_id: '123',
|
|
1326
1482
|
},
|
|
1327
1483
|
]);
|
|
1328
1484
|
for (const choice of contentChoiceDeltas(`it's raining`)) {
|
|
@@ -1339,8 +1495,21 @@ describe('resource completions', () => {
|
|
|
1339
1495
|
]);
|
|
1340
1496
|
|
|
1341
1497
|
expect(listener.eventMessages).toEqual([
|
|
1342
|
-
{
|
|
1343
|
-
|
|
1498
|
+
{
|
|
1499
|
+
role: 'assistant',
|
|
1500
|
+
content: null,
|
|
1501
|
+
tool_calls: [
|
|
1502
|
+
{
|
|
1503
|
+
type: 'function',
|
|
1504
|
+
id: '123',
|
|
1505
|
+
function: {
|
|
1506
|
+
arguments: '',
|
|
1507
|
+
name: 'getWeather',
|
|
1508
|
+
},
|
|
1509
|
+
},
|
|
1510
|
+
],
|
|
1511
|
+
},
|
|
1512
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '123' },
|
|
1344
1513
|
{ role: 'assistant', content: "it's raining" },
|
|
1345
1514
|
]);
|
|
1346
1515
|
expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
|
|
@@ -1352,18 +1521,21 @@ describe('resource completions', () => {
|
|
|
1352
1521
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1353
1522
|
|
|
1354
1523
|
const controller = new AbortController();
|
|
1355
|
-
const runner = openai.beta.chat.completions.
|
|
1524
|
+
const runner = openai.beta.chat.completions.runTools(
|
|
1356
1525
|
{
|
|
1357
1526
|
stream: true,
|
|
1358
1527
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1359
1528
|
model: 'gpt-3.5-turbo',
|
|
1360
|
-
|
|
1529
|
+
tools: [
|
|
1361
1530
|
{
|
|
1362
|
-
|
|
1363
|
-
|
|
1531
|
+
type: 'function',
|
|
1532
|
+
function: {
|
|
1533
|
+
function: function getWeather() {
|
|
1534
|
+
return `it's raining`;
|
|
1535
|
+
},
|
|
1536
|
+
parameters: {},
|
|
1537
|
+
description: 'gets the weather',
|
|
1364
1538
|
},
|
|
1365
|
-
parameters: {},
|
|
1366
|
-
description: 'gets the weather',
|
|
1367
1539
|
},
|
|
1368
1540
|
],
|
|
1369
1541
|
},
|
|
@@ -1383,10 +1555,17 @@ describe('resource completions', () => {
|
|
|
1383
1555
|
delta: {
|
|
1384
1556
|
role: 'assistant',
|
|
1385
1557
|
content: null,
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1558
|
+
tool_calls: [
|
|
1559
|
+
{
|
|
1560
|
+
type: 'function',
|
|
1561
|
+
index: 0,
|
|
1562
|
+
id: '123',
|
|
1563
|
+
function: {
|
|
1564
|
+
arguments: '',
|
|
1565
|
+
name: 'getWeather',
|
|
1566
|
+
},
|
|
1567
|
+
},
|
|
1568
|
+
],
|
|
1390
1569
|
},
|
|
1391
1570
|
},
|
|
1392
1571
|
],
|
|
@@ -1399,8 +1578,21 @@ describe('resource completions', () => {
|
|
|
1399
1578
|
await runner.done().catch(() => {});
|
|
1400
1579
|
|
|
1401
1580
|
expect(listener.eventMessages).toEqual([
|
|
1402
|
-
{
|
|
1403
|
-
|
|
1581
|
+
{
|
|
1582
|
+
role: 'assistant',
|
|
1583
|
+
content: null,
|
|
1584
|
+
tool_calls: [
|
|
1585
|
+
{
|
|
1586
|
+
type: 'function',
|
|
1587
|
+
id: '123',
|
|
1588
|
+
function: {
|
|
1589
|
+
arguments: '',
|
|
1590
|
+
name: 'getWeather',
|
|
1591
|
+
},
|
|
1592
|
+
},
|
|
1593
|
+
],
|
|
1594
|
+
},
|
|
1595
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '123' },
|
|
1404
1596
|
]);
|
|
1405
1597
|
expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
|
|
1406
1598
|
await listener.sanityCheck({ error: 'Request was aborted.' });
|
|
@@ -1411,7 +1603,7 @@ describe('resource completions', () => {
|
|
|
1411
1603
|
|
|
1412
1604
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1413
1605
|
|
|
1414
|
-
const runner = openai.beta.chat.completions.
|
|
1606
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1415
1607
|
stream: true,
|
|
1416
1608
|
messages: [
|
|
1417
1609
|
{
|
|
@@ -1420,8 +1612,8 @@ describe('resource completions', () => {
|
|
|
1420
1612
|
},
|
|
1421
1613
|
],
|
|
1422
1614
|
model: 'gpt-3.5-turbo',
|
|
1423
|
-
|
|
1424
|
-
new
|
|
1615
|
+
tools: [
|
|
1616
|
+
new ParsingToolFunction({
|
|
1425
1617
|
name: 'numProperties',
|
|
1426
1618
|
function: (obj: object) => String(Object.keys(obj).length),
|
|
1427
1619
|
parameters: { type: 'object' },
|
|
@@ -1455,10 +1647,17 @@ describe('resource completions', () => {
|
|
|
1455
1647
|
delta: {
|
|
1456
1648
|
role: 'assistant',
|
|
1457
1649
|
content: null,
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1650
|
+
tool_calls: [
|
|
1651
|
+
{
|
|
1652
|
+
type: 'function',
|
|
1653
|
+
id: '123',
|
|
1654
|
+
index: 0,
|
|
1655
|
+
function: {
|
|
1656
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
1657
|
+
name: 'numProperties',
|
|
1658
|
+
},
|
|
1659
|
+
},
|
|
1660
|
+
],
|
|
1462
1661
|
},
|
|
1463
1662
|
},
|
|
1464
1663
|
],
|
|
@@ -1476,15 +1675,21 @@ describe('resource completions', () => {
|
|
|
1476
1675
|
{
|
|
1477
1676
|
role: 'assistant',
|
|
1478
1677
|
content: null,
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1678
|
+
tool_calls: [
|
|
1679
|
+
{
|
|
1680
|
+
type: 'function',
|
|
1681
|
+
id: '123',
|
|
1682
|
+
function: {
|
|
1683
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
1684
|
+
name: 'numProperties',
|
|
1685
|
+
},
|
|
1686
|
+
},
|
|
1687
|
+
],
|
|
1483
1688
|
},
|
|
1484
1689
|
{
|
|
1485
|
-
role: '
|
|
1690
|
+
role: 'tool',
|
|
1486
1691
|
content: '3',
|
|
1487
|
-
|
|
1692
|
+
tool_call_id: '123',
|
|
1488
1693
|
},
|
|
1489
1694
|
]);
|
|
1490
1695
|
for (const choice of contentChoiceDeltas(`there are 3 properties in {"a": 1, "b": 2, "c": 3}`)) {
|
|
@@ -1504,9 +1709,15 @@ describe('resource completions', () => {
|
|
|
1504
1709
|
{
|
|
1505
1710
|
role: 'assistant',
|
|
1506
1711
|
content: null,
|
|
1507
|
-
|
|
1712
|
+
tool_calls: [
|
|
1713
|
+
{
|
|
1714
|
+
type: 'function',
|
|
1715
|
+
id: '123',
|
|
1716
|
+
function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
|
|
1717
|
+
},
|
|
1718
|
+
],
|
|
1508
1719
|
},
|
|
1509
|
-
{ role: '
|
|
1720
|
+
{ role: 'tool', content: '3', tool_call_id: '123' },
|
|
1510
1721
|
{ role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
|
|
1511
1722
|
]);
|
|
1512
1723
|
expect(listener.eventFunctionCallResults).toEqual(['3']);
|
|
@@ -1517,7 +1728,7 @@ describe('resource completions', () => {
|
|
|
1517
1728
|
|
|
1518
1729
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1519
1730
|
|
|
1520
|
-
const runner = openai.beta.chat.completions.
|
|
1731
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1521
1732
|
stream: true,
|
|
1522
1733
|
messages: [
|
|
1523
1734
|
{
|
|
@@ -1526,8 +1737,8 @@ describe('resource completions', () => {
|
|
|
1526
1737
|
},
|
|
1527
1738
|
],
|
|
1528
1739
|
model: 'gpt-3.5-turbo',
|
|
1529
|
-
|
|
1530
|
-
new
|
|
1740
|
+
tools: [
|
|
1741
|
+
new ParsingToolFunction({
|
|
1531
1742
|
name: 'numProperties',
|
|
1532
1743
|
function: (obj: object) => String(Object.keys(obj).length),
|
|
1533
1744
|
parameters: { type: 'object' },
|
|
@@ -1552,7 +1763,10 @@ describe('resource completions', () => {
|
|
|
1552
1763
|
content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
|
|
1553
1764
|
},
|
|
1554
1765
|
]);
|
|
1555
|
-
for (const choice of functionCallDeltas('[{"a": 1, "b": 2, "c": 3}]', {
|
|
1766
|
+
for (const choice of functionCallDeltas('[{"a": 1, "b": 2, "c": 3}]', {
|
|
1767
|
+
name: 'numProperties',
|
|
1768
|
+
id: '123',
|
|
1769
|
+
})) {
|
|
1556
1770
|
yield {
|
|
1557
1771
|
id: '1',
|
|
1558
1772
|
choices: [choice],
|
|
@@ -1571,18 +1785,27 @@ describe('resource completions', () => {
|
|
|
1571
1785
|
{
|
|
1572
1786
|
role: 'assistant',
|
|
1573
1787
|
content: null,
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1788
|
+
tool_calls: [
|
|
1789
|
+
{
|
|
1790
|
+
type: 'function',
|
|
1791
|
+
id: '123',
|
|
1792
|
+
function: {
|
|
1793
|
+
arguments: '[{"a": 1, "b": 2, "c": 3}]',
|
|
1794
|
+
name: 'numProperties',
|
|
1795
|
+
},
|
|
1796
|
+
},
|
|
1797
|
+
],
|
|
1578
1798
|
},
|
|
1579
1799
|
{
|
|
1580
|
-
role: '
|
|
1800
|
+
role: 'tool',
|
|
1581
1801
|
content: `must be an object`,
|
|
1582
|
-
|
|
1802
|
+
tool_call_id: '123',
|
|
1583
1803
|
},
|
|
1584
1804
|
]);
|
|
1585
|
-
for (const choice of functionCallDeltas('{"a": 1, "b": 2, "c": 3}', {
|
|
1805
|
+
for (const choice of functionCallDeltas('{"a": 1, "b": 2, "c": 3}', {
|
|
1806
|
+
name: 'numProperties',
|
|
1807
|
+
id: '1234',
|
|
1808
|
+
})) {
|
|
1586
1809
|
yield {
|
|
1587
1810
|
id: '2',
|
|
1588
1811
|
choices: [choice],
|
|
@@ -1601,28 +1824,40 @@ describe('resource completions', () => {
|
|
|
1601
1824
|
{
|
|
1602
1825
|
role: 'assistant',
|
|
1603
1826
|
content: null,
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1827
|
+
tool_calls: [
|
|
1828
|
+
{
|
|
1829
|
+
type: 'function',
|
|
1830
|
+
id: '123',
|
|
1831
|
+
function: {
|
|
1832
|
+
arguments: '[{"a": 1, "b": 2, "c": 3}]',
|
|
1833
|
+
name: 'numProperties',
|
|
1834
|
+
},
|
|
1835
|
+
},
|
|
1836
|
+
],
|
|
1608
1837
|
},
|
|
1609
1838
|
{
|
|
1610
|
-
role: '
|
|
1839
|
+
role: 'tool',
|
|
1611
1840
|
content: `must be an object`,
|
|
1612
|
-
|
|
1841
|
+
tool_call_id: '123',
|
|
1613
1842
|
},
|
|
1614
1843
|
{
|
|
1615
1844
|
role: 'assistant',
|
|
1616
1845
|
content: null,
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1846
|
+
tool_calls: [
|
|
1847
|
+
{
|
|
1848
|
+
type: 'function',
|
|
1849
|
+
id: '1234',
|
|
1850
|
+
function: {
|
|
1851
|
+
arguments: '{"a": 1, "b": 2, "c": 3}',
|
|
1852
|
+
name: 'numProperties',
|
|
1853
|
+
},
|
|
1854
|
+
},
|
|
1855
|
+
],
|
|
1621
1856
|
},
|
|
1622
1857
|
{
|
|
1623
|
-
role: '
|
|
1858
|
+
role: 'tool',
|
|
1624
1859
|
content: '3',
|
|
1625
|
-
|
|
1860
|
+
tool_call_id: '1234',
|
|
1626
1861
|
},
|
|
1627
1862
|
]);
|
|
1628
1863
|
for (const choice of contentChoiceDeltas(`there are 3 properties in {"a": 1, "b": 2, "c": 3}`)) {
|
|
@@ -1642,15 +1877,27 @@ describe('resource completions', () => {
|
|
|
1642
1877
|
{
|
|
1643
1878
|
role: 'assistant',
|
|
1644
1879
|
content: null,
|
|
1645
|
-
|
|
1880
|
+
tool_calls: [
|
|
1881
|
+
{
|
|
1882
|
+
type: 'function',
|
|
1883
|
+
id: '123',
|
|
1884
|
+
function: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
|
|
1885
|
+
},
|
|
1886
|
+
],
|
|
1646
1887
|
},
|
|
1647
|
-
{ role: '
|
|
1888
|
+
{ role: 'tool', content: `must be an object`, tool_call_id: '123' },
|
|
1648
1889
|
{
|
|
1649
1890
|
role: 'assistant',
|
|
1650
1891
|
content: null,
|
|
1651
|
-
|
|
1892
|
+
tool_calls: [
|
|
1893
|
+
{
|
|
1894
|
+
type: 'function',
|
|
1895
|
+
id: '1234',
|
|
1896
|
+
function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
|
|
1897
|
+
},
|
|
1898
|
+
],
|
|
1652
1899
|
},
|
|
1653
|
-
{ role: '
|
|
1900
|
+
{ role: 'tool', content: '3', tool_call_id: '1234' },
|
|
1654
1901
|
{ role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
|
|
1655
1902
|
]);
|
|
1656
1903
|
expect(listener.eventFunctionCallResults).toEqual([`must be an object`, '3']);
|
|
@@ -1661,20 +1908,26 @@ describe('resource completions', () => {
|
|
|
1661
1908
|
|
|
1662
1909
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1663
1910
|
|
|
1664
|
-
const runner = openai.beta.chat.completions.
|
|
1911
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1665
1912
|
stream: true,
|
|
1666
1913
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1667
1914
|
model: 'gpt-3.5-turbo',
|
|
1668
|
-
|
|
1669
|
-
|
|
1915
|
+
tool_choice: {
|
|
1916
|
+
type: 'function',
|
|
1917
|
+
function: {
|
|
1918
|
+
name: 'getWeather',
|
|
1919
|
+
},
|
|
1670
1920
|
},
|
|
1671
|
-
|
|
1921
|
+
tools: [
|
|
1672
1922
|
{
|
|
1673
|
-
|
|
1674
|
-
|
|
1923
|
+
type: 'function',
|
|
1924
|
+
function: {
|
|
1925
|
+
function: function getWeather() {
|
|
1926
|
+
return `it's raining`;
|
|
1927
|
+
},
|
|
1928
|
+
parameters: {},
|
|
1929
|
+
description: 'gets the weather',
|
|
1675
1930
|
},
|
|
1676
|
-
parameters: {},
|
|
1677
|
-
description: 'gets the weather',
|
|
1678
1931
|
},
|
|
1679
1932
|
],
|
|
1680
1933
|
});
|
|
@@ -1692,10 +1945,17 @@ describe('resource completions', () => {
|
|
|
1692
1945
|
delta: {
|
|
1693
1946
|
role: 'assistant',
|
|
1694
1947
|
content: null,
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1948
|
+
tool_calls: [
|
|
1949
|
+
{
|
|
1950
|
+
type: 'function',
|
|
1951
|
+
index: 0,
|
|
1952
|
+
id: '123',
|
|
1953
|
+
function: {
|
|
1954
|
+
arguments: '',
|
|
1955
|
+
name: 'getWeather',
|
|
1956
|
+
},
|
|
1957
|
+
},
|
|
1958
|
+
],
|
|
1699
1959
|
},
|
|
1700
1960
|
},
|
|
1701
1961
|
],
|
|
@@ -1708,8 +1968,21 @@ describe('resource completions', () => {
|
|
|
1708
1968
|
]);
|
|
1709
1969
|
|
|
1710
1970
|
expect(listener.eventMessages).toEqual([
|
|
1711
|
-
{
|
|
1712
|
-
|
|
1971
|
+
{
|
|
1972
|
+
role: 'assistant',
|
|
1973
|
+
content: null,
|
|
1974
|
+
tool_calls: [
|
|
1975
|
+
{
|
|
1976
|
+
type: 'function',
|
|
1977
|
+
id: '123',
|
|
1978
|
+
function: {
|
|
1979
|
+
arguments: '',
|
|
1980
|
+
name: 'getWeather',
|
|
1981
|
+
},
|
|
1982
|
+
},
|
|
1983
|
+
],
|
|
1984
|
+
},
|
|
1985
|
+
{ role: 'tool', tool_call_id: '123', content: `it's raining` },
|
|
1713
1986
|
]);
|
|
1714
1987
|
expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
|
|
1715
1988
|
await listener.sanityCheck();
|
|
@@ -1719,17 +1992,20 @@ describe('resource completions', () => {
|
|
|
1719
1992
|
|
|
1720
1993
|
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1721
1994
|
|
|
1722
|
-
const runner = openai.beta.chat.completions.
|
|
1995
|
+
const runner = openai.beta.chat.completions.runTools({
|
|
1723
1996
|
stream: true,
|
|
1724
1997
|
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1725
1998
|
model: 'gpt-3.5-turbo',
|
|
1726
|
-
|
|
1999
|
+
tools: [
|
|
1727
2000
|
{
|
|
1728
|
-
|
|
1729
|
-
|
|
2001
|
+
type: 'function',
|
|
2002
|
+
function: {
|
|
2003
|
+
function: function getWeather() {
|
|
2004
|
+
return `it's raining`;
|
|
2005
|
+
},
|
|
2006
|
+
parameters: {},
|
|
2007
|
+
description: 'gets the weather',
|
|
1730
2008
|
},
|
|
1731
|
-
parameters: {},
|
|
1732
|
-
description: 'gets the weather',
|
|
1733
2009
|
},
|
|
1734
2010
|
],
|
|
1735
2011
|
});
|
|
@@ -1747,10 +2023,17 @@ describe('resource completions', () => {
|
|
|
1747
2023
|
delta: {
|
|
1748
2024
|
role: 'assistant',
|
|
1749
2025
|
content: null,
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
2026
|
+
tool_calls: [
|
|
2027
|
+
{
|
|
2028
|
+
type: 'function',
|
|
2029
|
+
index: 0,
|
|
2030
|
+
id: '123',
|
|
2031
|
+
function: {
|
|
2032
|
+
arguments: '',
|
|
2033
|
+
name: 'get_weather',
|
|
2034
|
+
},
|
|
2035
|
+
},
|
|
2036
|
+
],
|
|
1754
2037
|
},
|
|
1755
2038
|
},
|
|
1756
2039
|
],
|
|
@@ -1765,15 +2048,21 @@ describe('resource completions', () => {
|
|
|
1765
2048
|
{
|
|
1766
2049
|
role: 'assistant',
|
|
1767
2050
|
content: null,
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
2051
|
+
tool_calls: [
|
|
2052
|
+
{
|
|
2053
|
+
type: 'function',
|
|
2054
|
+
id: '123',
|
|
2055
|
+
function: {
|
|
2056
|
+
arguments: '',
|
|
2057
|
+
name: 'get_weather',
|
|
2058
|
+
},
|
|
2059
|
+
},
|
|
2060
|
+
],
|
|
1772
2061
|
},
|
|
1773
2062
|
{
|
|
1774
|
-
role: '
|
|
1775
|
-
content: `Invalid
|
|
1776
|
-
|
|
2063
|
+
role: 'tool',
|
|
2064
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
2065
|
+
tool_call_id: '123',
|
|
1777
2066
|
},
|
|
1778
2067
|
]);
|
|
1779
2068
|
yield {
|
|
@@ -1785,10 +2074,17 @@ describe('resource completions', () => {
|
|
|
1785
2074
|
delta: {
|
|
1786
2075
|
role: 'assistant',
|
|
1787
2076
|
content: null,
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2077
|
+
tool_calls: [
|
|
2078
|
+
{
|
|
2079
|
+
type: 'function',
|
|
2080
|
+
index: 0,
|
|
2081
|
+
id: '1234',
|
|
2082
|
+
function: {
|
|
2083
|
+
arguments: '',
|
|
2084
|
+
name: 'getWeather',
|
|
2085
|
+
},
|
|
2086
|
+
},
|
|
2087
|
+
],
|
|
1792
2088
|
},
|
|
1793
2089
|
},
|
|
1794
2090
|
],
|
|
@@ -1803,28 +2099,40 @@ describe('resource completions', () => {
|
|
|
1803
2099
|
{
|
|
1804
2100
|
role: 'assistant',
|
|
1805
2101
|
content: null,
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
2102
|
+
tool_calls: [
|
|
2103
|
+
{
|
|
2104
|
+
type: 'function',
|
|
2105
|
+
id: '123',
|
|
2106
|
+
function: {
|
|
2107
|
+
arguments: '',
|
|
2108
|
+
name: 'get_weather',
|
|
2109
|
+
},
|
|
2110
|
+
},
|
|
2111
|
+
],
|
|
1810
2112
|
},
|
|
1811
2113
|
{
|
|
1812
|
-
role: '
|
|
1813
|
-
content: `Invalid
|
|
1814
|
-
|
|
2114
|
+
role: 'tool',
|
|
2115
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
2116
|
+
tool_call_id: '123',
|
|
1815
2117
|
},
|
|
1816
2118
|
{
|
|
1817
2119
|
role: 'assistant',
|
|
1818
2120
|
content: null,
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
2121
|
+
tool_calls: [
|
|
2122
|
+
{
|
|
2123
|
+
type: 'function',
|
|
2124
|
+
id: '1234',
|
|
2125
|
+
function: {
|
|
2126
|
+
arguments: '',
|
|
2127
|
+
name: 'getWeather',
|
|
2128
|
+
},
|
|
2129
|
+
},
|
|
2130
|
+
],
|
|
1823
2131
|
},
|
|
1824
2132
|
{
|
|
1825
|
-
role: '
|
|
2133
|
+
role: 'tool',
|
|
1826
2134
|
content: `it's raining`,
|
|
1827
|
-
|
|
2135
|
+
tool_call_id: '1234',
|
|
1828
2136
|
},
|
|
1829
2137
|
]);
|
|
1830
2138
|
for (const choice of contentChoiceDeltas(`it's raining`)) {
|
|
@@ -1841,83 +2149,45 @@ describe('resource completions', () => {
|
|
|
1841
2149
|
]);
|
|
1842
2150
|
|
|
1843
2151
|
expect(listener.eventMessages).toEqual([
|
|
1844
|
-
{ role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
|
|
1845
2152
|
{
|
|
1846
|
-
role: '
|
|
1847
|
-
content:
|
|
1848
|
-
|
|
2153
|
+
role: 'assistant',
|
|
2154
|
+
content: null,
|
|
2155
|
+
tool_calls: [
|
|
2156
|
+
{
|
|
2157
|
+
type: 'function',
|
|
2158
|
+
id: '123',
|
|
2159
|
+
function: {
|
|
2160
|
+
arguments: '',
|
|
2161
|
+
name: 'get_weather',
|
|
2162
|
+
},
|
|
2163
|
+
},
|
|
2164
|
+
],
|
|
1849
2165
|
},
|
|
1850
|
-
{
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
expect(listener.eventFunctionCallResults).toEqual([
|
|
1855
|
-
`Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
1856
|
-
`it's raining`,
|
|
1857
|
-
]);
|
|
1858
|
-
await listener.sanityCheck();
|
|
1859
|
-
});
|
|
1860
|
-
test('wrong function name with single function call', async () => {
|
|
1861
|
-
const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
|
|
1862
|
-
|
|
1863
|
-
const openai = new OpenAI({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
|
|
1864
|
-
|
|
1865
|
-
const runner = openai.beta.chat.completions.runFunctions({
|
|
1866
|
-
stream: true,
|
|
1867
|
-
messages: [{ role: 'user', content: 'tell me what the weather is like' }],
|
|
1868
|
-
model: 'gpt-3.5-turbo',
|
|
1869
|
-
function_call: {
|
|
1870
|
-
name: 'getWeather',
|
|
2166
|
+
{
|
|
2167
|
+
role: 'tool',
|
|
2168
|
+
content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
2169
|
+
tool_call_id: '123',
|
|
1871
2170
|
},
|
|
1872
|
-
functions: [
|
|
1873
|
-
{
|
|
1874
|
-
function: function getWeather() {
|
|
1875
|
-
return `it's raining`;
|
|
1876
|
-
},
|
|
1877
|
-
parameters: {},
|
|
1878
|
-
description: 'gets the weather',
|
|
1879
|
-
},
|
|
1880
|
-
],
|
|
1881
|
-
});
|
|
1882
|
-
const listener = new StreamingRunnerListener(runner);
|
|
1883
|
-
|
|
1884
|
-
await Promise.all([
|
|
1885
|
-
handleRequest(async function* (request): AsyncIterable<OpenAI.Chat.ChatCompletionChunk> {
|
|
1886
|
-
expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
|
|
1887
|
-
yield {
|
|
1888
|
-
id: '1',
|
|
1889
|
-
choices: [
|
|
1890
|
-
{
|
|
1891
|
-
index: 0,
|
|
1892
|
-
finish_reason: 'function_call',
|
|
1893
|
-
delta: {
|
|
1894
|
-
role: 'assistant',
|
|
1895
|
-
content: null,
|
|
1896
|
-
function_call: {
|
|
1897
|
-
arguments: '',
|
|
1898
|
-
name: 'get_weather',
|
|
1899
|
-
},
|
|
1900
|
-
},
|
|
1901
|
-
},
|
|
1902
|
-
],
|
|
1903
|
-
created: Math.floor(Date.now() / 1000),
|
|
1904
|
-
model: 'gpt-3.5-turbo',
|
|
1905
|
-
object: 'chat.completion.chunk',
|
|
1906
|
-
};
|
|
1907
|
-
}),
|
|
1908
|
-
runner.done(),
|
|
1909
|
-
]);
|
|
1910
|
-
|
|
1911
|
-
expect(listener.eventMessages).toEqual([
|
|
1912
|
-
{ role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
|
|
1913
2171
|
{
|
|
1914
|
-
role: '
|
|
1915
|
-
content:
|
|
1916
|
-
|
|
2172
|
+
role: 'assistant',
|
|
2173
|
+
content: null,
|
|
2174
|
+
tool_calls: [
|
|
2175
|
+
{
|
|
2176
|
+
type: 'function',
|
|
2177
|
+
id: '1234',
|
|
2178
|
+
function: {
|
|
2179
|
+
arguments: '',
|
|
2180
|
+
name: 'getWeather',
|
|
2181
|
+
},
|
|
2182
|
+
},
|
|
2183
|
+
],
|
|
1917
2184
|
},
|
|
2185
|
+
{ role: 'tool', content: `it's raining`, tool_call_id: '1234' },
|
|
2186
|
+
{ role: 'assistant', content: "it's raining" },
|
|
1918
2187
|
]);
|
|
1919
2188
|
expect(listener.eventFunctionCallResults).toEqual([
|
|
1920
|
-
`Invalid
|
|
2189
|
+
`Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
|
|
2190
|
+
`it's raining`,
|
|
1921
2191
|
]);
|
|
1922
2192
|
await listener.sanityCheck();
|
|
1923
2193
|
});
|