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.
Files changed (95) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +3 -3
  3. package/error.d.ts.map +1 -1
  4. package/error.js +2 -1
  5. package/error.js.map +1 -1
  6. package/error.mjs +2 -1
  7. package/error.mjs.map +1 -1
  8. package/index.d.mts +7 -5
  9. package/index.d.ts +7 -5
  10. package/index.d.ts.map +1 -1
  11. package/index.js +5 -5
  12. package/index.js.map +1 -1
  13. package/index.mjs +5 -5
  14. package/index.mjs.map +1 -1
  15. package/lib/AbstractChatCompletionRunner.d.ts +1 -1
  16. package/lib/AbstractChatCompletionRunner.d.ts.map +1 -1
  17. package/lib/AbstractChatCompletionRunner.js +21 -6
  18. package/lib/AbstractChatCompletionRunner.js.map +1 -1
  19. package/lib/AbstractChatCompletionRunner.mjs +21 -6
  20. package/lib/AbstractChatCompletionRunner.mjs.map +1 -1
  21. package/lib/ChatCompletionRunFunctions.test.js +823 -549
  22. package/lib/ChatCompletionRunFunctions.test.js.map +1 -1
  23. package/lib/ChatCompletionRunFunctions.test.mjs +824 -550
  24. package/lib/ChatCompletionRunFunctions.test.mjs.map +1 -1
  25. package/lib/ChatCompletionRunner.d.ts +1 -0
  26. package/lib/ChatCompletionRunner.d.ts.map +1 -1
  27. package/lib/ChatCompletionRunner.js +11 -2
  28. package/lib/ChatCompletionRunner.js.map +1 -1
  29. package/lib/ChatCompletionRunner.mjs +11 -2
  30. package/lib/ChatCompletionRunner.mjs.map +1 -1
  31. package/lib/ChatCompletionStreamingRunner.d.ts +1 -0
  32. package/lib/ChatCompletionStreamingRunner.d.ts.map +1 -1
  33. package/lib/ChatCompletionStreamingRunner.js +7 -4
  34. package/lib/ChatCompletionStreamingRunner.js.map +1 -1
  35. package/lib/ChatCompletionStreamingRunner.mjs +7 -4
  36. package/lib/ChatCompletionStreamingRunner.mjs.map +1 -1
  37. package/lib/RunnableFunction.d.ts +19 -3
  38. package/lib/RunnableFunction.d.ts.map +1 -1
  39. package/lib/RunnableFunction.js +14 -1
  40. package/lib/RunnableFunction.js.map +1 -1
  41. package/lib/RunnableFunction.mjs +12 -0
  42. package/lib/RunnableFunction.mjs.map +1 -1
  43. package/package.json +3 -2
  44. package/resources/audio/speech.d.ts +3 -1
  45. package/resources/audio/speech.d.ts.map +1 -1
  46. package/resources/audio/speech.js.map +1 -1
  47. package/resources/audio/speech.mjs.map +1 -1
  48. package/resources/beta/chat/completions.d.ts +2 -8
  49. package/resources/beta/chat/completions.d.ts.map +1 -1
  50. package/resources/beta/chat/completions.js +2 -1
  51. package/resources/beta/chat/completions.js.map +1 -1
  52. package/resources/beta/chat/completions.mjs +1 -1
  53. package/resources/beta/chat/completions.mjs.map +1 -1
  54. package/resources/chat/completions.d.ts +52 -34
  55. package/resources/chat/completions.d.ts.map +1 -1
  56. package/resources/chat/completions.js.map +1 -1
  57. package/resources/chat/completions.mjs.map +1 -1
  58. package/resources/completions.d.ts +2 -2
  59. package/resources/embeddings.d.ts +2 -1
  60. package/resources/embeddings.d.ts.map +1 -1
  61. package/resources/embeddings.js.map +1 -1
  62. package/resources/embeddings.mjs.map +1 -1
  63. package/resources/files.d.ts +3 -3
  64. package/resources/files.js +3 -3
  65. package/resources/files.mjs +3 -3
  66. package/resources/shared.d.ts +12 -14
  67. package/resources/shared.d.ts.map +1 -1
  68. package/src/error.ts +2 -1
  69. package/src/index.ts +8 -5
  70. package/src/lib/AbstractChatCompletionRunner.ts +37 -13
  71. package/src/lib/ChatCompletionRunFunctions.test.ts +828 -558
  72. package/src/lib/ChatCompletionRunner.ts +11 -2
  73. package/src/lib/ChatCompletionStreamingRunner.ts +11 -12
  74. package/src/lib/RunnableFunction.ts +33 -7
  75. package/src/resources/audio/speech.ts +3 -1
  76. package/src/resources/beta/chat/completions.ts +2 -7
  77. package/src/resources/chat/completions.ts +56 -35
  78. package/src/resources/completions.ts +2 -2
  79. package/src/resources/embeddings.ts +2 -1
  80. package/src/resources/files.ts +3 -3
  81. package/src/resources/shared.ts +13 -15
  82. package/src/streaming.ts +4 -1
  83. package/src/uploads.ts +2 -3
  84. package/src/version.ts +1 -1
  85. package/streaming.d.ts.map +1 -1
  86. package/streaming.js.map +1 -1
  87. package/streaming.mjs.map +1 -1
  88. package/uploads.d.ts.map +1 -1
  89. package/uploads.js +2 -1
  90. package/uploads.js.map +1 -1
  91. package/uploads.mjs +2 -1
  92. package/uploads.mjs.map +1 -1
  93. package/version.d.ts +1 -1
  94. package/version.js +1 -1
  95. package/version.mjs +1 -1
@@ -52,11 +52,15 @@ function mockFetch() {
52
52
  ]);
53
53
  }
54
54
  function handleRequest(handle) {
55
- return new Promise((resolve) => {
55
+ return new Promise((resolve, reject) => {
56
56
  fetchQueue.shift()?.(async (req, init) => {
57
57
  try {
58
58
  return await handle(req, init);
59
59
  }
60
+ catch (err) {
61
+ reject(err);
62
+ return err;
63
+ }
60
64
  finally {
61
65
  resolve();
62
66
  }
@@ -126,7 +130,7 @@ function* contentChoiceDeltas(content, { index = 0, role = 'assistant', } = {})
126
130
  }
127
131
  // functionCallDeltas returns an async iterator which mocks a delta stream of a functionCall by splitting
128
132
  // the argument into chunks separated by whitespace.
129
- function* functionCallDeltas(args, { index = 0, name, role = 'assistant', }) {
133
+ function* functionCallDeltas(args, { index = 0, id = '123', name, role = 'assistant', }) {
130
134
  const deltas = args.split(/\s+/g);
131
135
  for (let i = 0; i < deltas.length; i++) {
132
136
  yield {
@@ -134,10 +138,17 @@ function* functionCallDeltas(args, { index = 0, name, role = 'assistant', }) {
134
138
  finish_reason: i === deltas.length - 1 ? 'function_call' : null,
135
139
  delta: {
136
140
  role,
137
- function_call: {
138
- arguments: `${deltas[i] || ''}${i === deltas.length - 1 ? '' : ' '}`,
139
- ...(i === deltas.length - 1 ? { name } : null),
140
- },
141
+ tool_calls: [
142
+ {
143
+ type: 'function',
144
+ index: 0,
145
+ id,
146
+ function: {
147
+ arguments: `${deltas[i] || ''}${i === deltas.length - 1 ? '' : ' '}`,
148
+ ...(i === deltas.length - 1 ? { name } : null),
149
+ },
150
+ },
151
+ ],
141
152
  },
142
153
  };
143
154
  }
@@ -169,7 +180,7 @@ class RunnerListener {
169
180
  .on('finalFunctionCallResult', (result) => (this.finalFunctionCallResult = result))
170
181
  .on('totalUsage', (usage) => (this.totalUsage = usage))
171
182
  .on('error', (error) => (this.error = error))
172
- .on('abort', () => (this.gotAbort = true))
183
+ .on('abort', (error) => ((this.error = error), (this.gotAbort = true)))
173
184
  .on('end', () => (this.gotEnd = true))
174
185
  .once('message', () => this.onceMessageCallCount++);
175
186
  }
@@ -215,7 +226,7 @@ class RunnerListener {
215
226
  .map((m) => m.content)
216
227
  .filter(Boolean);
217
228
  expect(this.contents).toEqual(expectedContents);
218
- expect(this.finalMessage).toEqual(this.messages[this.messages.length - 1]);
229
+ expect(this.finalMessage).toEqual([...this.messages].reverse().find((x) => x.role === 'assistant'));
219
230
  expect(await this.runner.finalMessage()).toEqual(this.finalMessage);
220
231
  expect(this.finalContent).toEqual(expectedContents[expectedContents.length - 1] ?? null);
221
232
  expect(await this.runner.finalContent()).toEqual(this.finalContent);
@@ -272,6 +283,7 @@ class StreamingRunnerListener {
272
283
  .on('finalFunctionCall', (functionCall) => (this.finalFunctionCall = functionCall))
273
284
  .on('finalFunctionCallResult', (result) => (this.finalFunctionCallResult = result))
274
285
  .on('error', (error) => (this.error = error))
286
+ .on('abort', (abort) => (this.error = abort))
275
287
  .on('end', () => (this.gotEnd = true));
276
288
  }
277
289
  async sanityCheck({ error } = {}) {
@@ -307,7 +319,7 @@ class StreamingRunnerListener {
307
319
  return;
308
320
  if (this.eventContents.length)
309
321
  expect(this.eventChunks.length).toBeGreaterThan(0);
310
- expect(this.finalMessage).toEqual(this.eventMessages[this.eventMessages.length - 1]);
322
+ expect(this.finalMessage).toEqual([...this.eventMessages].reverse().find((x) => x.role === 'assistant'));
311
323
  expect(await this.runner.finalMessage()).toEqual(this.finalMessage);
312
324
  expect(this.finalContent).toEqual(this.eventContents[this.eventContents.length - 1]?.[1] ?? null);
313
325
  expect(await this.runner.finalContent()).toEqual(this.finalContent);
@@ -332,45 +344,54 @@ class StreamingRunnerListener {
332
344
  }
333
345
  function _typeTests() {
334
346
  const openai = new openai_1.default();
335
- openai.beta.chat.completions.runFunctions({
347
+ openai.beta.chat.completions.runTools({
336
348
  messages: [
337
349
  { role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
338
350
  ],
339
351
  model: 'gpt-3.5-turbo',
340
- functions: [
352
+ tools: [
341
353
  {
342
- name: 'numProperties',
343
- function: (obj) => String(Object.keys(obj).length),
344
- parameters: { type: 'object' },
345
- parse: (str) => {
346
- const result = JSON.parse(str);
347
- if (!(result instanceof Object) || Array.isArray(result)) {
348
- throw new Error('must be an object');
349
- }
350
- return result;
354
+ type: 'function',
355
+ function: {
356
+ name: 'numProperties',
357
+ function: (obj) => String(Object.keys(obj).length),
358
+ parameters: { type: 'object' },
359
+ parse: (str) => {
360
+ const result = JSON.parse(str);
361
+ if (!(result instanceof Object) || Array.isArray(result)) {
362
+ throw new Error('must be an object');
363
+ }
364
+ return result;
365
+ },
366
+ description: 'gets the number of properties on an object',
351
367
  },
352
- description: 'gets the number of properties on an object',
353
368
  },
354
369
  {
355
- function: (str) => String(str.length),
356
- parameters: { type: 'string' },
357
- description: 'gets the length of a string',
370
+ type: 'function',
371
+ function: {
372
+ function: (str) => String(str.length),
373
+ parameters: { type: 'string' },
374
+ description: 'gets the length of a string',
375
+ },
358
376
  },
359
- // @ts-expect-error function must accept string if parse is omitted
360
377
  {
361
- function: (obj) => String(Object.keys(obj).length),
362
- parameters: { type: 'object' },
363
- description: 'gets the number of properties on an object',
378
+ type: 'function',
379
+ // @ts-expect-error function must accept string if parse is omitted
380
+ function: {
381
+ function: (obj) => String(Object.keys(obj).length),
382
+ parameters: { type: 'object' },
383
+ description: 'gets the number of properties on an object',
384
+ },
364
385
  },
365
386
  ],
366
387
  });
367
- openai.beta.chat.completions.runFunctions({
388
+ openai.beta.chat.completions.runTools({
368
389
  messages: [
369
390
  { role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
370
391
  ],
371
392
  model: 'gpt-3.5-turbo',
372
- functions: [
373
- new completions_1.ParsingFunction({
393
+ tools: [
394
+ new completions_1.ParsingToolFunction({
374
395
  name: 'numProperties',
375
396
  // @ts-expect-error parse and function don't match
376
397
  parse: (str) => str,
@@ -380,13 +401,13 @@ function _typeTests() {
380
401
  }),
381
402
  ],
382
403
  });
383
- openai.beta.chat.completions.runFunctions({
404
+ openai.beta.chat.completions.runTools({
384
405
  messages: [
385
406
  { role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
386
407
  ],
387
408
  model: 'gpt-3.5-turbo',
388
- functions: [
389
- new completions_1.ParsingFunction({
409
+ tools: [
410
+ new completions_1.ParsingToolFunction({
390
411
  name: 'numProperties',
391
412
  parse: (str) => {
392
413
  const result = JSON.parse(str);
@@ -399,7 +420,7 @@ function _typeTests() {
399
420
  parameters: { type: 'object' },
400
421
  description: 'gets the number of properties on an object',
401
422
  }),
402
- new completions_1.ParsingFunction({
423
+ new completions_1.ParsingToolFunction({
403
424
  name: 'keys',
404
425
  parse: (str) => {
405
426
  const result = JSON.parse(str);
@@ -412,7 +433,7 @@ function _typeTests() {
412
433
  parameters: { type: 'object' },
413
434
  description: 'gets the number of properties on an object',
414
435
  }),
415
- new completions_1.ParsingFunction({
436
+ new completions_1.ParsingToolFunction({
416
437
  name: 'len2',
417
438
  // @ts-expect-error parse and function don't match
418
439
  parse: (str) => str,
@@ -422,135 +443,169 @@ function _typeTests() {
422
443
  }),
423
444
  ],
424
445
  });
425
- openai.beta.chat.completions.runFunctions({
446
+ openai.beta.chat.completions.runTools({
426
447
  messages: [
427
448
  { role: 'user', content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}' },
428
449
  ],
429
450
  model: 'gpt-3.5-turbo',
430
451
  // @ts-ignore error occurs here in TS 4
431
- functions: [
452
+ tools: [
432
453
  {
433
- name: 'numProperties',
434
- parse: (str) => {
435
- const result = JSON.parse(str);
436
- if (!(result instanceof Object) || Array.isArray(result)) {
437
- throw new Error('must be an object');
438
- }
439
- return result;
454
+ type: 'function',
455
+ function: {
456
+ name: 'numProperties',
457
+ parse: (str) => {
458
+ const result = JSON.parse(str);
459
+ if (!(result instanceof Object) || Array.isArray(result)) {
460
+ throw new Error('must be an object');
461
+ }
462
+ return result;
463
+ },
464
+ function: (obj) => String(Object.keys(obj).length),
465
+ parameters: { type: 'object' },
466
+ description: 'gets the number of properties on an object',
440
467
  },
441
- function: (obj) => String(Object.keys(obj).length),
442
- parameters: { type: 'object' },
443
- description: 'gets the number of properties on an object',
444
468
  },
445
469
  {
446
- name: 'keys',
447
- parse: (str) => {
448
- const result = JSON.parse(str);
449
- if (!(result instanceof Object)) {
450
- throw new Error('must be an Object');
451
- }
452
- return result;
470
+ type: 'function',
471
+ function: {
472
+ name: 'keys',
473
+ parse: (str) => {
474
+ const result = JSON.parse(str);
475
+ if (!(result instanceof Object)) {
476
+ throw new Error('must be an Object');
477
+ }
478
+ return result;
479
+ },
480
+ function: (obj) => Object.keys(obj).join(', '),
481
+ parameters: { type: 'object' },
482
+ description: 'gets the number of properties on an object',
453
483
  },
454
- function: (obj) => Object.keys(obj).join(', '),
455
- parameters: { type: 'object' },
456
- description: 'gets the number of properties on an object',
457
484
  },
458
485
  {
459
- name: 'len2',
460
- parse: (str) => str,
461
- // @ts-ignore error occurs here in TS 5
462
- // function input doesn't match parse output
463
- function: (obj) => String(Object.keys(obj).length),
464
- parameters: { type: 'object' },
465
- description: 'gets the number of properties on an object',
486
+ type: 'function',
487
+ function: {
488
+ name: 'len2',
489
+ parse: (str) => str,
490
+ // @ts-ignore error occurs here in TS 5
491
+ // function input doesn't match parse output
492
+ function: (obj) => String(Object.keys(obj).length),
493
+ parameters: { type: 'object' },
494
+ description: 'gets the number of properties on an object',
495
+ },
466
496
  },
467
497
  ],
468
498
  });
469
499
  }
470
500
  describe('resource completions', () => {
471
- // TODO: re-enable
472
- describe.skip('runFunctions with stream: false', () => {
501
+ describe('runTools with stream: false', () => {
473
502
  test('successful flow', async () => {
474
503
  const { fetch, handleRequest } = mockChatCompletionFetch();
475
504
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
476
- const runner = openai.beta.chat.completions.runFunctions({
505
+ const runner = openai.beta.chat.completions.runTools({
477
506
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
478
507
  model: 'gpt-3.5-turbo',
479
- functions: [
508
+ tools: [
480
509
  {
481
- function: function getWeather() {
482
- return `it's raining`;
510
+ type: 'function',
511
+ function: {
512
+ function: function getWeather() {
513
+ return `it's raining`;
514
+ },
515
+ parameters: {},
516
+ description: 'gets the weather',
483
517
  },
484
- parameters: {},
485
- description: 'gets the weather',
486
518
  },
487
519
  ],
488
520
  });
489
521
  const listener = new RunnerListener(runner);
490
- await Promise.all([
491
- handleRequest(async (request) => {
492
- expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
493
- return {
494
- id: '1',
495
- choices: [
496
- {
497
- index: 0,
498
- finish_reason: 'function_call',
499
- message: {
500
- role: 'assistant',
501
- content: null,
502
- function_call: {
503
- arguments: '',
504
- name: 'getWeather',
505
- },
506
- },
507
- },
508
- ],
509
- created: Math.floor(Date.now() / 1000),
510
- model: 'gpt-3.5-turbo',
511
- object: 'chat.completion',
512
- };
513
- }),
514
- handleRequest(async (request) => {
515
- expect(request.messages).toEqual([
516
- { role: 'user', content: 'tell me what the weather is like' },
522
+ await handleRequest(async (request) => {
523
+ expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
524
+ return {
525
+ id: '1',
526
+ choices: [
517
527
  {
518
- role: 'assistant',
519
- content: null,
520
- function_call: {
521
- arguments: '',
522
- name: 'getWeather',
528
+ index: 0,
529
+ finish_reason: 'function_call',
530
+ message: {
531
+ role: 'assistant',
532
+ content: null,
533
+ tool_calls: [
534
+ {
535
+ type: 'function',
536
+ id: '123',
537
+ function: {
538
+ arguments: '',
539
+ name: 'getWeather',
540
+ },
541
+ },
542
+ ],
523
543
  },
524
544
  },
525
- {
526
- role: 'function',
527
- content: `it's raining`,
528
- name: 'getWeather',
529
- },
530
- ]);
531
- return {
532
- id: '2',
533
- choices: [
545
+ ],
546
+ created: Math.floor(Date.now() / 1000),
547
+ model: 'gpt-3.5-turbo',
548
+ object: 'chat.completion',
549
+ };
550
+ });
551
+ await handleRequest(async (request) => {
552
+ expect(request.messages).toEqual([
553
+ { role: 'user', content: 'tell me what the weather is like' },
554
+ {
555
+ role: 'assistant',
556
+ content: null,
557
+ tool_calls: [
534
558
  {
535
- index: 0,
536
- finish_reason: 'stop',
537
- message: {
538
- role: 'assistant',
539
- content: `it's raining`,
559
+ type: 'function',
560
+ id: '123',
561
+ function: {
562
+ arguments: '',
563
+ name: 'getWeather',
540
564
  },
541
565
  },
542
566
  ],
543
- created: Math.floor(Date.now() / 1000),
544
- model: 'gpt-3.5-turbo',
545
- object: 'chat.completion',
546
- };
547
- }),
548
- runner.done(),
549
- ]);
567
+ },
568
+ {
569
+ role: 'tool',
570
+ content: `it's raining`,
571
+ tool_call_id: '123',
572
+ },
573
+ ]);
574
+ return {
575
+ id: '2',
576
+ choices: [
577
+ {
578
+ index: 0,
579
+ finish_reason: 'stop',
580
+ message: {
581
+ role: 'assistant',
582
+ content: `it's raining`,
583
+ },
584
+ },
585
+ ],
586
+ created: Math.floor(Date.now() / 1000),
587
+ model: 'gpt-3.5-turbo',
588
+ object: 'chat.completion',
589
+ };
590
+ });
591
+ await runner.done();
550
592
  expect(listener.messages).toEqual([
551
593
  { role: 'user', content: 'tell me what the weather is like' },
552
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
553
- { role: 'function', content: `it's raining`, name: 'getWeather' },
594
+ {
595
+ role: 'assistant',
596
+ content: null,
597
+ tool_calls: [
598
+ {
599
+ type: 'function',
600
+ id: '123',
601
+ function: {
602
+ arguments: '',
603
+ name: 'getWeather',
604
+ },
605
+ },
606
+ ],
607
+ },
608
+ { role: 'tool', content: `it's raining`, tool_call_id: '123' },
554
609
  { role: 'assistant', content: "it's raining" },
555
610
  ]);
556
611
  expect(listener.functionCallResults).toEqual([`it's raining`]);
@@ -560,16 +615,19 @@ describe('resource completions', () => {
560
615
  const { fetch, handleRequest } = mockChatCompletionFetch();
561
616
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
562
617
  const controller = new AbortController();
563
- const runner = openai.beta.chat.completions.runFunctions({
618
+ const runner = openai.beta.chat.completions.runTools({
564
619
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
565
620
  model: 'gpt-3.5-turbo',
566
- functions: [
621
+ tools: [
567
622
  {
568
- function: function getWeather() {
569
- return `it's raining`;
623
+ type: 'function',
624
+ function: {
625
+ function: function getWeather() {
626
+ return `it's raining`;
627
+ },
628
+ parameters: {},
629
+ description: 'gets the weather',
570
630
  },
571
- parameters: {},
572
- description: 'gets the weather',
573
631
  },
574
632
  ],
575
633
  }, { signal: controller.signal });
@@ -585,10 +643,16 @@ describe('resource completions', () => {
585
643
  message: {
586
644
  role: 'assistant',
587
645
  content: null,
588
- function_call: {
589
- arguments: '',
590
- name: 'getWeather',
591
- },
646
+ tool_calls: [
647
+ {
648
+ type: 'function',
649
+ id: '123',
650
+ function: {
651
+ arguments: '',
652
+ name: 'getWeather',
653
+ },
654
+ },
655
+ ],
592
656
  },
593
657
  },
594
658
  ],
@@ -601,8 +665,21 @@ describe('resource completions', () => {
601
665
  await runner.done().catch(() => { });
602
666
  expect(listener.messages).toEqual([
603
667
  { role: 'user', content: 'tell me what the weather is like' },
604
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
605
- { role: 'function', content: `it's raining`, name: 'getWeather' },
668
+ {
669
+ role: 'assistant',
670
+ content: null,
671
+ tool_calls: [
672
+ {
673
+ type: 'function',
674
+ id: '123',
675
+ function: {
676
+ arguments: '',
677
+ name: 'getWeather',
678
+ },
679
+ },
680
+ ],
681
+ },
682
+ { role: 'tool', content: `it's raining`, tool_call_id: '123' },
606
683
  ]);
607
684
  expect(listener.functionCallResults).toEqual([`it's raining`]);
608
685
  await listener.sanityCheck({ error: 'Request was aborted.' });
@@ -611,7 +688,7 @@ describe('resource completions', () => {
611
688
  test('successful flow with parse', async () => {
612
689
  const { fetch, handleRequest } = mockChatCompletionFetch();
613
690
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
614
- const runner = openai.beta.chat.completions.runFunctions({
691
+ const runner = openai.beta.chat.completions.runTools({
615
692
  messages: [
616
693
  {
617
694
  role: 'user',
@@ -619,8 +696,8 @@ describe('resource completions', () => {
619
696
  },
620
697
  ],
621
698
  model: 'gpt-3.5-turbo',
622
- functions: [
623
- new completions_1.ParsingFunction({
699
+ tools: [
700
+ new completions_1.ParsingToolFunction({
624
701
  name: 'numProperties',
625
702
  function: (obj) => String(Object.keys(obj).length),
626
703
  parameters: { type: 'object' },
@@ -636,84 +713,94 @@ describe('resource completions', () => {
636
713
  ],
637
714
  });
638
715
  const listener = new RunnerListener(runner);
639
- await Promise.all([
640
- handleRequest(async (request) => {
641
- expect(request.messages).toEqual([
716
+ await handleRequest(async (request) => {
717
+ expect(request.messages).toEqual([
718
+ {
719
+ role: 'user',
720
+ content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
721
+ },
722
+ ]);
723
+ return {
724
+ id: '1',
725
+ choices: [
642
726
  {
643
- role: 'user',
644
- content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
645
- },
646
- ]);
647
- return {
648
- id: '1',
649
- choices: [
650
- {
651
- index: 0,
652
- finish_reason: 'function_call',
653
- message: {
654
- role: 'assistant',
655
- content: null,
656
- function_call: {
657
- arguments: '{"a": 1, "b": 2, "c": 3}',
658
- name: 'numProperties',
727
+ index: 0,
728
+ finish_reason: 'function_call',
729
+ message: {
730
+ role: 'assistant',
731
+ content: null,
732
+ tool_calls: [
733
+ {
734
+ type: 'function',
735
+ id: '123',
736
+ function: {
737
+ arguments: '{"a": 1, "b": 2, "c": 3}',
738
+ name: 'numProperties',
739
+ },
659
740
  },
660
- },
661
- },
662
- ],
663
- created: Math.floor(Date.now() / 1000),
664
- model: 'gpt-3.5-turbo',
665
- object: 'chat.completion',
666
- usage: {
667
- completion_tokens: 5,
668
- prompt_tokens: 20,
669
- total_tokens: 25,
670
- },
671
- };
672
- }),
673
- handleRequest(async (request) => {
674
- expect(request.messages).toEqual([
675
- {
676
- role: 'user',
677
- content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
678
- },
679
- {
680
- role: 'assistant',
681
- content: null,
682
- function_call: {
683
- arguments: '{"a": 1, "b": 2, "c": 3}',
684
- name: 'numProperties',
741
+ ],
685
742
  },
686
743
  },
687
- {
688
- role: 'function',
689
- content: '3',
690
- name: 'numProperties',
691
- },
692
- ]);
693
- return {
694
- id: '2',
695
- choices: [
744
+ ],
745
+ created: Math.floor(Date.now() / 1000),
746
+ model: 'gpt-3.5-turbo',
747
+ object: 'chat.completion',
748
+ usage: {
749
+ completion_tokens: 5,
750
+ prompt_tokens: 20,
751
+ total_tokens: 25,
752
+ },
753
+ };
754
+ });
755
+ await handleRequest(async (request) => {
756
+ expect(request.messages).toEqual([
757
+ {
758
+ role: 'user',
759
+ content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
760
+ },
761
+ {
762
+ role: 'assistant',
763
+ content: null,
764
+ tool_calls: [
696
765
  {
697
- index: 0,
698
- finish_reason: 'stop',
699
- message: {
700
- role: 'assistant',
701
- content: `there are 3 properties in {"a": 1, "b": 2, "c": 3}`,
766
+ type: 'function',
767
+ id: '123',
768
+ function: {
769
+ arguments: '{"a": 1, "b": 2, "c": 3}',
770
+ name: 'numProperties',
702
771
  },
703
772
  },
704
773
  ],
705
- created: Math.floor(Date.now() / 1000),
706
- model: 'gpt-3.5-turbo',
707
- object: 'chat.completion',
708
- usage: {
709
- completion_tokens: 10,
710
- prompt_tokens: 25,
711
- total_tokens: 35,
774
+ },
775
+ {
776
+ role: 'tool',
777
+ content: '3',
778
+ tool_call_id: '123',
779
+ },
780
+ ]);
781
+ return {
782
+ id: '2',
783
+ choices: [
784
+ {
785
+ index: 0,
786
+ finish_reason: 'stop',
787
+ message: {
788
+ role: 'assistant',
789
+ content: `there are 3 properties in {"a": 1, "b": 2, "c": 3}`,
790
+ },
712
791
  },
713
- };
714
- }),
715
- runner.done(),
716
- ]);
792
+ ],
793
+ created: Math.floor(Date.now() / 1000),
794
+ model: 'gpt-3.5-turbo',
795
+ object: 'chat.completion',
796
+ usage: {
797
+ completion_tokens: 10,
798
+ prompt_tokens: 25,
799
+ total_tokens: 35,
800
+ },
801
+ };
802
+ });
803
+ await runner.done();
717
804
  expect(listener.messages).toEqual([
718
805
  {
719
806
  role: 'user',
@@ -722,9 +809,15 @@ describe('resource completions', () => {
722
809
  {
723
810
  role: 'assistant',
724
811
  content: null,
725
- function_call: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
812
+ tool_calls: [
813
+ {
814
+ type: 'function',
815
+ id: '123',
816
+ function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
817
+ },
818
+ ],
726
819
  },
727
- { role: 'function', content: '3', name: 'numProperties' },
820
+ { role: 'tool', content: '3', tool_call_id: '123' },
728
821
  { role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
729
822
  ]);
730
823
  expect(listener.functionCallResults).toEqual(['3']);
@@ -733,7 +826,7 @@ describe('resource completions', () => {
733
826
  test('flow with parse error', async () => {
734
827
  const { fetch, handleRequest } = mockChatCompletionFetch();
735
828
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
736
- const runner = openai.beta.chat.completions.runFunctions({
829
+ const runner = openai.beta.chat.completions.runTools({
737
830
  messages: [
738
831
  {
739
832
  role: 'user',
@@ -741,8 +834,8 @@ describe('resource completions', () => {
741
834
  },
742
835
  ],
743
836
  model: 'gpt-3.5-turbo',
744
- functions: [
745
- new completions_1.ParsingFunction({
837
+ tools: [
838
+ new completions_1.ParsingToolFunction({
746
839
  name: 'numProperties',
747
840
  function: (obj) => String(Object.keys(obj).length),
748
841
  parameters: { type: 'object' },
@@ -775,10 +868,16 @@ describe('resource completions', () => {
775
868
  message: {
776
869
  role: 'assistant',
777
870
  content: null,
778
- function_call: {
779
- arguments: '[{"a": 1, "b": 2, "c": 3}]',
780
- name: 'numProperties',
781
- },
871
+ tool_calls: [
872
+ {
873
+ type: 'function',
874
+ id: '123',
875
+ function: {
876
+ arguments: '[{"a": 1, "b": 2, "c": 3}]',
877
+ name: 'numProperties',
878
+ },
879
+ },
880
+ ],
782
881
  },
783
882
  },
784
883
  ],
@@ -796,15 +895,21 @@ describe('resource completions', () => {
796
895
  {
797
896
  role: 'assistant',
798
897
  content: null,
799
- function_call: {
800
- arguments: '[{"a": 1, "b": 2, "c": 3}]',
801
- name: 'numProperties',
802
- },
898
+ tool_calls: [
899
+ {
900
+ type: 'function',
901
+ id: '123',
902
+ function: {
903
+ arguments: '[{"a": 1, "b": 2, "c": 3}]',
904
+ name: 'numProperties',
905
+ },
906
+ },
907
+ ],
803
908
  },
804
909
  {
805
- role: 'function',
910
+ role: 'tool',
806
911
  content: `must be an object`,
807
- name: 'numProperties',
912
+ tool_call_id: '123',
808
913
  },
809
914
  ]);
810
915
  return {
@@ -816,10 +921,16 @@ describe('resource completions', () => {
816
921
  message: {
817
922
  role: 'assistant',
818
923
  content: null,
819
- function_call: {
820
- arguments: '{"a": 1, "b": 2, "c": 3}',
821
- name: 'numProperties',
822
- },
924
+ tool_calls: [
925
+ {
926
+ type: 'function',
927
+ id: '1234',
928
+ function: {
929
+ arguments: '{"a": 1, "b": 2, "c": 3}',
930
+ name: 'numProperties',
931
+ },
932
+ },
933
+ ],
823
934
  },
824
935
  },
825
936
  ],
@@ -837,28 +948,40 @@ describe('resource completions', () => {
837
948
  {
838
949
  role: 'assistant',
839
950
  content: null,
840
- function_call: {
841
- arguments: '[{"a": 1, "b": 2, "c": 3}]',
842
- name: 'numProperties',
843
- },
951
+ tool_calls: [
952
+ {
953
+ type: 'function',
954
+ id: '123',
955
+ function: {
956
+ arguments: '[{"a": 1, "b": 2, "c": 3}]',
957
+ name: 'numProperties',
958
+ },
959
+ },
960
+ ],
844
961
  },
845
962
  {
846
- role: 'function',
963
+ role: 'tool',
847
964
  content: `must be an object`,
848
- name: 'numProperties',
965
+ tool_call_id: '123',
849
966
  },
850
967
  {
851
968
  role: 'assistant',
852
969
  content: null,
853
- function_call: {
854
- arguments: '{"a": 1, "b": 2, "c": 3}',
855
- name: 'numProperties',
856
- },
970
+ tool_calls: [
971
+ {
972
+ type: 'function',
973
+ id: '1234',
974
+ function: {
975
+ arguments: '{"a": 1, "b": 2, "c": 3}',
976
+ name: 'numProperties',
977
+ },
978
+ },
979
+ ],
857
980
  },
858
981
  {
859
- role: 'function',
982
+ role: 'tool',
860
983
  content: '3',
861
- name: 'numProperties',
984
+ tool_call_id: '1234',
862
985
  },
863
986
  ]);
864
987
  return {
@@ -888,15 +1011,27 @@ describe('resource completions', () => {
888
1011
  {
889
1012
  role: 'assistant',
890
1013
  content: null,
891
- function_call: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
1014
+ tool_calls: [
1015
+ {
1016
+ type: 'function',
1017
+ id: '123',
1018
+ function: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
1019
+ },
1020
+ ],
892
1021
  },
893
- { role: 'function', content: `must be an object`, name: 'numProperties' },
1022
+ { role: 'tool', content: `must be an object`, tool_call_id: '123' },
894
1023
  {
895
1024
  role: 'assistant',
896
1025
  content: null,
897
- function_call: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1026
+ tool_calls: [
1027
+ {
1028
+ type: 'function',
1029
+ id: '1234',
1030
+ function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1031
+ },
1032
+ ],
898
1033
  },
899
- { role: 'function', content: '3', name: 'numProperties' },
1034
+ { role: 'tool', content: '3', tool_call_id: '1234' },
900
1035
  { role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
901
1036
  ]);
902
1037
  expect(listener.functionCallResults).toEqual([`must be an object`, '3']);
@@ -905,19 +1040,25 @@ describe('resource completions', () => {
905
1040
  test('single function call', async () => {
906
1041
  const { fetch, handleRequest } = mockChatCompletionFetch();
907
1042
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
908
- const runner = openai.beta.chat.completions.runFunctions({
1043
+ const runner = openai.beta.chat.completions.runTools({
909
1044
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
910
1045
  model: 'gpt-3.5-turbo',
911
- function_call: {
912
- name: 'getWeather',
1046
+ tool_choice: {
1047
+ type: 'function',
1048
+ function: {
1049
+ name: 'getWeather',
1050
+ },
913
1051
  },
914
- functions: [
1052
+ tools: [
915
1053
  {
916
- function: function getWeather() {
917
- return `it's raining`;
1054
+ type: 'function',
1055
+ function: {
1056
+ function: function getWeather() {
1057
+ return `it's raining`;
1058
+ },
1059
+ parameters: {},
1060
+ description: 'gets the weather',
918
1061
  },
919
- parameters: {},
920
- description: 'gets the weather',
921
1062
  },
922
1063
  ],
923
1064
  });
@@ -934,10 +1075,16 @@ describe('resource completions', () => {
934
1075
  message: {
935
1076
  role: 'assistant',
936
1077
  content: null,
937
- function_call: {
938
- arguments: '',
939
- name: 'getWeather',
940
- },
1078
+ tool_calls: [
1079
+ {
1080
+ type: 'function',
1081
+ id: '123',
1082
+ function: {
1083
+ arguments: '',
1084
+ name: 'getWeather',
1085
+ },
1086
+ },
1087
+ ],
941
1088
  },
942
1089
  },
943
1090
  ],
@@ -950,8 +1097,21 @@ describe('resource completions', () => {
950
1097
  ]);
951
1098
  expect(listener.messages).toEqual([
952
1099
  { role: 'user', content: 'tell me what the weather is like' },
953
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
954
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1100
+ {
1101
+ role: 'assistant',
1102
+ content: null,
1103
+ tool_calls: [
1104
+ {
1105
+ type: 'function',
1106
+ id: '123',
1107
+ function: {
1108
+ arguments: '',
1109
+ name: 'getWeather',
1110
+ },
1111
+ },
1112
+ ],
1113
+ },
1114
+ { role: 'tool', content: `it's raining`, tool_call_id: '123' },
955
1115
  ]);
956
1116
  expect(listener.functionCallResults).toEqual([`it's raining`]);
957
1117
  await listener.sanityCheck();
@@ -959,16 +1119,19 @@ describe('resource completions', () => {
959
1119
  test('wrong function name', async () => {
960
1120
  const { fetch, handleRequest } = mockChatCompletionFetch();
961
1121
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
962
- const runner = openai.beta.chat.completions.runFunctions({
1122
+ const runner = openai.beta.chat.completions.runTools({
963
1123
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
964
1124
  model: 'gpt-3.5-turbo',
965
- functions: [
1125
+ tools: [
966
1126
  {
967
- function: function getWeather() {
968
- return `it's raining`;
1127
+ type: 'function',
1128
+ function: {
1129
+ function: function getWeather() {
1130
+ return `it's raining`;
1131
+ },
1132
+ parameters: {},
1133
+ description: 'gets the weather',
969
1134
  },
970
- parameters: {},
971
- description: 'gets the weather',
972
1135
  },
973
1136
  ],
974
1137
  });
@@ -985,10 +1148,16 @@ describe('resource completions', () => {
985
1148
  message: {
986
1149
  role: 'assistant',
987
1150
  content: null,
988
- function_call: {
989
- arguments: '',
990
- name: 'get_weather',
991
- },
1151
+ tool_calls: [
1152
+ {
1153
+ type: 'function',
1154
+ id: '123',
1155
+ function: {
1156
+ arguments: '',
1157
+ name: 'get_weather',
1158
+ },
1159
+ },
1160
+ ],
992
1161
  },
993
1162
  },
994
1163
  ],
@@ -1003,15 +1172,21 @@ describe('resource completions', () => {
1003
1172
  {
1004
1173
  role: 'assistant',
1005
1174
  content: null,
1006
- function_call: {
1007
- arguments: '',
1008
- name: 'get_weather',
1009
- },
1175
+ tool_calls: [
1176
+ {
1177
+ type: 'function',
1178
+ id: '123',
1179
+ function: {
1180
+ arguments: '',
1181
+ name: 'get_weather',
1182
+ },
1183
+ },
1184
+ ],
1010
1185
  },
1011
1186
  {
1012
- role: 'function',
1013
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1014
- name: 'get_weather',
1187
+ role: 'tool',
1188
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1189
+ tool_call_id: '123',
1015
1190
  },
1016
1191
  ]);
1017
1192
  return {
@@ -1023,10 +1198,16 @@ describe('resource completions', () => {
1023
1198
  message: {
1024
1199
  role: 'assistant',
1025
1200
  content: null,
1026
- function_call: {
1027
- arguments: '',
1028
- name: 'getWeather',
1029
- },
1201
+ tool_calls: [
1202
+ {
1203
+ type: 'function',
1204
+ id: '1234',
1205
+ function: {
1206
+ arguments: '',
1207
+ name: 'getWeather',
1208
+ },
1209
+ },
1210
+ ],
1030
1211
  },
1031
1212
  },
1032
1213
  ],
@@ -1041,28 +1222,40 @@ describe('resource completions', () => {
1041
1222
  {
1042
1223
  role: 'assistant',
1043
1224
  content: null,
1044
- function_call: {
1045
- arguments: '',
1046
- name: 'get_weather',
1047
- },
1225
+ tool_calls: [
1226
+ {
1227
+ type: 'function',
1228
+ id: '123',
1229
+ function: {
1230
+ arguments: '',
1231
+ name: 'get_weather',
1232
+ },
1233
+ },
1234
+ ],
1048
1235
  },
1049
1236
  {
1050
- role: 'function',
1051
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1052
- name: 'get_weather',
1237
+ role: 'tool',
1238
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1239
+ tool_call_id: '123',
1053
1240
  },
1054
1241
  {
1055
1242
  role: 'assistant',
1056
1243
  content: null,
1057
- function_call: {
1058
- arguments: '',
1059
- name: 'getWeather',
1060
- },
1244
+ tool_calls: [
1245
+ {
1246
+ type: 'function',
1247
+ id: '1234',
1248
+ function: {
1249
+ arguments: '',
1250
+ name: 'getWeather',
1251
+ },
1252
+ },
1253
+ ],
1061
1254
  },
1062
1255
  {
1063
- role: 'function',
1256
+ role: 'tool',
1064
1257
  content: `it's raining`,
1065
- name: 'getWeather',
1258
+ tool_call_id: '1234',
1066
1259
  },
1067
1260
  ]);
1068
1261
  return {
@@ -1086,99 +1279,49 @@ describe('resource completions', () => {
1086
1279
  ]);
1087
1280
  expect(listener.messages).toEqual([
1088
1281
  { role: 'user', content: 'tell me what the weather is like' },
1089
- { role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
1090
1282
  {
1091
- role: 'function',
1092
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1093
- name: 'get_weather',
1283
+ role: 'assistant',
1284
+ content: null,
1285
+ tool_calls: [{ type: 'function', id: '123', function: { name: 'get_weather', arguments: '' } }],
1094
1286
  },
1095
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
1096
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1097
- { role: 'assistant', content: "it's raining" },
1098
- ]);
1099
- expect(listener.functionCallResults).toEqual([
1100
- `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1101
- `it's raining`,
1102
- ]);
1103
- await listener.sanityCheck();
1104
- });
1105
- test('wrong function name with single function call', async () => {
1106
- const { fetch, handleRequest } = mockChatCompletionFetch();
1107
- const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1108
- const runner = openai.beta.chat.completions.runFunctions({
1109
- messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1110
- model: 'gpt-3.5-turbo',
1111
- function_call: {
1112
- name: 'getWeather',
1287
+ {
1288
+ role: 'tool',
1289
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1290
+ tool_call_id: '123',
1113
1291
  },
1114
- functions: [
1115
- {
1116
- function: function getWeather() {
1117
- return `it's raining`;
1118
- },
1119
- parameters: {},
1120
- description: 'gets the weather',
1121
- },
1122
- ],
1123
- });
1124
- const listener = new RunnerListener(runner);
1125
- await Promise.all([
1126
- handleRequest(async (request) => {
1127
- expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
1128
- return {
1129
- id: '1',
1130
- choices: [
1131
- {
1132
- index: 0,
1133
- finish_reason: 'function_call',
1134
- message: {
1135
- role: 'assistant',
1136
- content: null,
1137
- function_call: {
1138
- arguments: '',
1139
- name: 'get_weather',
1140
- },
1141
- },
1142
- },
1143
- ],
1144
- created: Math.floor(Date.now() / 1000),
1145
- model: 'gpt-3.5-turbo',
1146
- object: 'chat.completion',
1147
- };
1148
- }),
1149
- runner.done(),
1150
- ]);
1151
- expect(listener.messages).toEqual([
1152
- { role: 'user', content: 'tell me what the weather is like' },
1153
- { role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
1154
1292
  {
1155
- role: 'function',
1156
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1157
- name: 'get_weather',
1293
+ role: 'assistant',
1294
+ content: null,
1295
+ tool_calls: [{ type: 'function', id: '1234', function: { name: 'getWeather', arguments: '' } }],
1158
1296
  },
1297
+ { role: 'tool', content: `it's raining`, tool_call_id: '1234' },
1298
+ { role: 'assistant', content: "it's raining" },
1159
1299
  ]);
1160
1300
  expect(listener.functionCallResults).toEqual([
1161
- `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1301
+ `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1302
+ `it's raining`,
1162
1303
  ]);
1163
1304
  await listener.sanityCheck();
1164
1305
  });
1165
1306
  });
1166
- // TODO: re-enable
1167
- describe.skip('runFunctions with stream: true', () => {
1307
+ describe('runTools with stream: true', () => {
1168
1308
  test('successful flow', async () => {
1169
1309
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1170
1310
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1171
- const runner = openai.beta.chat.completions.runFunctions({
1311
+ const runner = openai.beta.chat.completions.runTools({
1172
1312
  stream: true,
1173
1313
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1174
1314
  model: 'gpt-3.5-turbo',
1175
- functions: [
1315
+ tools: [
1176
1316
  {
1177
- function: function getWeather() {
1178
- return `it's raining`;
1317
+ type: 'function',
1318
+ function: {
1319
+ function: function getWeather() {
1320
+ return `it's raining`;
1321
+ },
1322
+ parameters: {},
1323
+ description: 'gets the weather',
1179
1324
  },
1180
- parameters: {},
1181
- description: 'gets the weather',
1182
1325
  },
1183
1326
  ],
1184
1327
  });
@@ -1195,10 +1338,17 @@ describe('resource completions', () => {
1195
1338
  delta: {
1196
1339
  role: 'assistant',
1197
1340
  content: null,
1198
- function_call: {
1199
- arguments: '',
1200
- name: 'getWeather',
1201
- },
1341
+ tool_calls: [
1342
+ {
1343
+ type: 'function',
1344
+ index: 0,
1345
+ id: '123',
1346
+ function: {
1347
+ arguments: '',
1348
+ name: 'getWeather',
1349
+ },
1350
+ },
1351
+ ],
1202
1352
  },
1203
1353
  },
1204
1354
  ],
@@ -1213,15 +1363,21 @@ describe('resource completions', () => {
1213
1363
  {
1214
1364
  role: 'assistant',
1215
1365
  content: null,
1216
- function_call: {
1217
- arguments: '',
1218
- name: 'getWeather',
1219
- },
1366
+ tool_calls: [
1367
+ {
1368
+ type: 'function',
1369
+ id: '123',
1370
+ function: {
1371
+ arguments: '',
1372
+ name: 'getWeather',
1373
+ },
1374
+ },
1375
+ ],
1220
1376
  },
1221
1377
  {
1222
- role: 'function',
1378
+ role: 'tool',
1223
1379
  content: `it's raining`,
1224
- name: 'getWeather',
1380
+ tool_call_id: '123',
1225
1381
  },
1226
1382
  ]);
1227
1383
  for (const choice of contentChoiceDeltas(`it's raining`)) {
@@ -1237,8 +1393,21 @@ describe('resource completions', () => {
1237
1393
  runner.done(),
1238
1394
  ]);
1239
1395
  expect(listener.eventMessages).toEqual([
1240
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
1241
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1396
+ {
1397
+ role: 'assistant',
1398
+ content: null,
1399
+ tool_calls: [
1400
+ {
1401
+ type: 'function',
1402
+ id: '123',
1403
+ function: {
1404
+ arguments: '',
1405
+ name: 'getWeather',
1406
+ },
1407
+ },
1408
+ ],
1409
+ },
1410
+ { role: 'tool', content: `it's raining`, tool_call_id: '123' },
1242
1411
  { role: 'assistant', content: "it's raining" },
1243
1412
  ]);
1244
1413
  expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
@@ -1248,17 +1417,20 @@ describe('resource completions', () => {
1248
1417
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1249
1418
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1250
1419
  const controller = new AbortController();
1251
- const runner = openai.beta.chat.completions.runFunctions({
1420
+ const runner = openai.beta.chat.completions.runTools({
1252
1421
  stream: true,
1253
1422
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1254
1423
  model: 'gpt-3.5-turbo',
1255
- functions: [
1424
+ tools: [
1256
1425
  {
1257
- function: function getWeather() {
1258
- return `it's raining`;
1426
+ type: 'function',
1427
+ function: {
1428
+ function: function getWeather() {
1429
+ return `it's raining`;
1430
+ },
1431
+ parameters: {},
1432
+ description: 'gets the weather',
1259
1433
  },
1260
- parameters: {},
1261
- description: 'gets the weather',
1262
1434
  },
1263
1435
  ],
1264
1436
  }, { signal: controller.signal });
@@ -1275,10 +1447,17 @@ describe('resource completions', () => {
1275
1447
  delta: {
1276
1448
  role: 'assistant',
1277
1449
  content: null,
1278
- function_call: {
1279
- arguments: '',
1280
- name: 'getWeather',
1281
- },
1450
+ tool_calls: [
1451
+ {
1452
+ type: 'function',
1453
+ index: 0,
1454
+ id: '123',
1455
+ function: {
1456
+ arguments: '',
1457
+ name: 'getWeather',
1458
+ },
1459
+ },
1460
+ ],
1282
1461
  },
1283
1462
  },
1284
1463
  ],
@@ -1289,8 +1468,21 @@ describe('resource completions', () => {
1289
1468
  });
1290
1469
  await runner.done().catch(() => { });
1291
1470
  expect(listener.eventMessages).toEqual([
1292
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
1293
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1471
+ {
1472
+ role: 'assistant',
1473
+ content: null,
1474
+ tool_calls: [
1475
+ {
1476
+ type: 'function',
1477
+ id: '123',
1478
+ function: {
1479
+ arguments: '',
1480
+ name: 'getWeather',
1481
+ },
1482
+ },
1483
+ ],
1484
+ },
1485
+ { role: 'tool', content: `it's raining`, tool_call_id: '123' },
1294
1486
  ]);
1295
1487
  expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
1296
1488
  await listener.sanityCheck({ error: 'Request was aborted.' });
@@ -1299,7 +1491,7 @@ describe('resource completions', () => {
1299
1491
  test('successful flow with parse', async () => {
1300
1492
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1301
1493
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1302
- const runner = openai.beta.chat.completions.runFunctions({
1494
+ const runner = openai.beta.chat.completions.runTools({
1303
1495
  stream: true,
1304
1496
  messages: [
1305
1497
  {
@@ -1308,8 +1500,8 @@ describe('resource completions', () => {
1308
1500
  },
1309
1501
  ],
1310
1502
  model: 'gpt-3.5-turbo',
1311
- functions: [
1312
- new completions_1.ParsingFunction({
1503
+ tools: [
1504
+ new completions_1.ParsingToolFunction({
1313
1505
  name: 'numProperties',
1314
1506
  function: (obj) => String(Object.keys(obj).length),
1315
1507
  parameters: { type: 'object' },
@@ -1342,10 +1534,17 @@ describe('resource completions', () => {
1342
1534
  delta: {
1343
1535
  role: 'assistant',
1344
1536
  content: null,
1345
- function_call: {
1346
- arguments: '{"a": 1, "b": 2, "c": 3}',
1347
- name: 'numProperties',
1348
- },
1537
+ tool_calls: [
1538
+ {
1539
+ type: 'function',
1540
+ id: '123',
1541
+ index: 0,
1542
+ function: {
1543
+ arguments: '{"a": 1, "b": 2, "c": 3}',
1544
+ name: 'numProperties',
1545
+ },
1546
+ },
1547
+ ],
1349
1548
  },
1350
1549
  },
1351
1550
  ],
@@ -1363,15 +1562,21 @@ describe('resource completions', () => {
1363
1562
  {
1364
1563
  role: 'assistant',
1365
1564
  content: null,
1366
- function_call: {
1367
- arguments: '{"a": 1, "b": 2, "c": 3}',
1368
- name: 'numProperties',
1369
- },
1565
+ tool_calls: [
1566
+ {
1567
+ type: 'function',
1568
+ id: '123',
1569
+ function: {
1570
+ arguments: '{"a": 1, "b": 2, "c": 3}',
1571
+ name: 'numProperties',
1572
+ },
1573
+ },
1574
+ ],
1370
1575
  },
1371
1576
  {
1372
- role: 'function',
1577
+ role: 'tool',
1373
1578
  content: '3',
1374
- name: 'numProperties',
1579
+ tool_call_id: '123',
1375
1580
  },
1376
1581
  ]);
1377
1582
  for (const choice of contentChoiceDeltas(`there are 3 properties in {"a": 1, "b": 2, "c": 3}`)) {
@@ -1390,9 +1595,15 @@ describe('resource completions', () => {
1390
1595
  {
1391
1596
  role: 'assistant',
1392
1597
  content: null,
1393
- function_call: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1598
+ tool_calls: [
1599
+ {
1600
+ type: 'function',
1601
+ id: '123',
1602
+ function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1603
+ },
1604
+ ],
1394
1605
  },
1395
- { role: 'function', content: '3', name: 'numProperties' },
1606
+ { role: 'tool', content: '3', tool_call_id: '123' },
1396
1607
  { role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
1397
1608
  ]);
1398
1609
  expect(listener.eventFunctionCallResults).toEqual(['3']);
@@ -1401,7 +1612,7 @@ describe('resource completions', () => {
1401
1612
  test('flow with parse error', async () => {
1402
1613
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1403
1614
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1404
- const runner = openai.beta.chat.completions.runFunctions({
1615
+ const runner = openai.beta.chat.completions.runTools({
1405
1616
  stream: true,
1406
1617
  messages: [
1407
1618
  {
@@ -1410,8 +1621,8 @@ describe('resource completions', () => {
1410
1621
  },
1411
1622
  ],
1412
1623
  model: 'gpt-3.5-turbo',
1413
- functions: [
1414
- new completions_1.ParsingFunction({
1624
+ tools: [
1625
+ new completions_1.ParsingToolFunction({
1415
1626
  name: 'numProperties',
1416
1627
  function: (obj) => String(Object.keys(obj).length),
1417
1628
  parameters: { type: 'object' },
@@ -1435,7 +1646,10 @@ describe('resource completions', () => {
1435
1646
  content: 'can you tell me how many properties are in {"a": 1, "b": 2, "c": 3}',
1436
1647
  },
1437
1648
  ]);
1438
- for (const choice of functionCallDeltas('[{"a": 1, "b": 2, "c": 3}]', { name: 'numProperties' })) {
1649
+ for (const choice of functionCallDeltas('[{"a": 1, "b": 2, "c": 3}]', {
1650
+ name: 'numProperties',
1651
+ id: '123',
1652
+ })) {
1439
1653
  yield {
1440
1654
  id: '1',
1441
1655
  choices: [choice],
@@ -1454,18 +1668,27 @@ describe('resource completions', () => {
1454
1668
  {
1455
1669
  role: 'assistant',
1456
1670
  content: null,
1457
- function_call: {
1458
- arguments: '[{"a": 1, "b": 2, "c": 3}]',
1459
- name: 'numProperties',
1460
- },
1671
+ tool_calls: [
1672
+ {
1673
+ type: 'function',
1674
+ id: '123',
1675
+ function: {
1676
+ arguments: '[{"a": 1, "b": 2, "c": 3}]',
1677
+ name: 'numProperties',
1678
+ },
1679
+ },
1680
+ ],
1461
1681
  },
1462
1682
  {
1463
- role: 'function',
1683
+ role: 'tool',
1464
1684
  content: `must be an object`,
1465
- name: 'numProperties',
1685
+ tool_call_id: '123',
1466
1686
  },
1467
1687
  ]);
1468
- for (const choice of functionCallDeltas('{"a": 1, "b": 2, "c": 3}', { name: 'numProperties' })) {
1688
+ for (const choice of functionCallDeltas('{"a": 1, "b": 2, "c": 3}', {
1689
+ name: 'numProperties',
1690
+ id: '1234',
1691
+ })) {
1469
1692
  yield {
1470
1693
  id: '2',
1471
1694
  choices: [choice],
@@ -1484,28 +1707,40 @@ describe('resource completions', () => {
1484
1707
  {
1485
1708
  role: 'assistant',
1486
1709
  content: null,
1487
- function_call: {
1488
- arguments: '[{"a": 1, "b": 2, "c": 3}]',
1489
- name: 'numProperties',
1490
- },
1710
+ tool_calls: [
1711
+ {
1712
+ type: 'function',
1713
+ id: '123',
1714
+ function: {
1715
+ arguments: '[{"a": 1, "b": 2, "c": 3}]',
1716
+ name: 'numProperties',
1717
+ },
1718
+ },
1719
+ ],
1491
1720
  },
1492
1721
  {
1493
- role: 'function',
1722
+ role: 'tool',
1494
1723
  content: `must be an object`,
1495
- name: 'numProperties',
1724
+ tool_call_id: '123',
1496
1725
  },
1497
1726
  {
1498
1727
  role: 'assistant',
1499
1728
  content: null,
1500
- function_call: {
1501
- arguments: '{"a": 1, "b": 2, "c": 3}',
1502
- name: 'numProperties',
1503
- },
1729
+ tool_calls: [
1730
+ {
1731
+ type: 'function',
1732
+ id: '1234',
1733
+ function: {
1734
+ arguments: '{"a": 1, "b": 2, "c": 3}',
1735
+ name: 'numProperties',
1736
+ },
1737
+ },
1738
+ ],
1504
1739
  },
1505
1740
  {
1506
- role: 'function',
1741
+ role: 'tool',
1507
1742
  content: '3',
1508
- name: 'numProperties',
1743
+ tool_call_id: '1234',
1509
1744
  },
1510
1745
  ]);
1511
1746
  for (const choice of contentChoiceDeltas(`there are 3 properties in {"a": 1, "b": 2, "c": 3}`)) {
@@ -1524,15 +1759,27 @@ describe('resource completions', () => {
1524
1759
  {
1525
1760
  role: 'assistant',
1526
1761
  content: null,
1527
- function_call: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
1762
+ tool_calls: [
1763
+ {
1764
+ type: 'function',
1765
+ id: '123',
1766
+ function: { name: 'numProperties', arguments: '[{"a": 1, "b": 2, "c": 3}]' },
1767
+ },
1768
+ ],
1528
1769
  },
1529
- { role: 'function', content: `must be an object`, name: 'numProperties' },
1770
+ { role: 'tool', content: `must be an object`, tool_call_id: '123' },
1530
1771
  {
1531
1772
  role: 'assistant',
1532
1773
  content: null,
1533
- function_call: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1774
+ tool_calls: [
1775
+ {
1776
+ type: 'function',
1777
+ id: '1234',
1778
+ function: { name: 'numProperties', arguments: '{"a": 1, "b": 2, "c": 3}' },
1779
+ },
1780
+ ],
1534
1781
  },
1535
- { role: 'function', content: '3', name: 'numProperties' },
1782
+ { role: 'tool', content: '3', tool_call_id: '1234' },
1536
1783
  { role: 'assistant', content: 'there are 3 properties in {"a": 1, "b": 2, "c": 3}' },
1537
1784
  ]);
1538
1785
  expect(listener.eventFunctionCallResults).toEqual([`must be an object`, '3']);
@@ -1541,20 +1788,26 @@ describe('resource completions', () => {
1541
1788
  test('single function call', async () => {
1542
1789
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1543
1790
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1544
- const runner = openai.beta.chat.completions.runFunctions({
1791
+ const runner = openai.beta.chat.completions.runTools({
1545
1792
  stream: true,
1546
1793
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1547
1794
  model: 'gpt-3.5-turbo',
1548
- function_call: {
1549
- name: 'getWeather',
1795
+ tool_choice: {
1796
+ type: 'function',
1797
+ function: {
1798
+ name: 'getWeather',
1799
+ },
1550
1800
  },
1551
- functions: [
1801
+ tools: [
1552
1802
  {
1553
- function: function getWeather() {
1554
- return `it's raining`;
1803
+ type: 'function',
1804
+ function: {
1805
+ function: function getWeather() {
1806
+ return `it's raining`;
1807
+ },
1808
+ parameters: {},
1809
+ description: 'gets the weather',
1555
1810
  },
1556
- parameters: {},
1557
- description: 'gets the weather',
1558
1811
  },
1559
1812
  ],
1560
1813
  });
@@ -1571,10 +1824,17 @@ describe('resource completions', () => {
1571
1824
  delta: {
1572
1825
  role: 'assistant',
1573
1826
  content: null,
1574
- function_call: {
1575
- arguments: '',
1576
- name: 'getWeather',
1577
- },
1827
+ tool_calls: [
1828
+ {
1829
+ type: 'function',
1830
+ index: 0,
1831
+ id: '123',
1832
+ function: {
1833
+ arguments: '',
1834
+ name: 'getWeather',
1835
+ },
1836
+ },
1837
+ ],
1578
1838
  },
1579
1839
  },
1580
1840
  ],
@@ -1586,8 +1846,21 @@ describe('resource completions', () => {
1586
1846
  runner.done(),
1587
1847
  ]);
1588
1848
  expect(listener.eventMessages).toEqual([
1589
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
1590
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1849
+ {
1850
+ role: 'assistant',
1851
+ content: null,
1852
+ tool_calls: [
1853
+ {
1854
+ type: 'function',
1855
+ id: '123',
1856
+ function: {
1857
+ arguments: '',
1858
+ name: 'getWeather',
1859
+ },
1860
+ },
1861
+ ],
1862
+ },
1863
+ { role: 'tool', tool_call_id: '123', content: `it's raining` },
1591
1864
  ]);
1592
1865
  expect(listener.eventFunctionCallResults).toEqual([`it's raining`]);
1593
1866
  await listener.sanityCheck();
@@ -1595,17 +1868,20 @@ describe('resource completions', () => {
1595
1868
  test('wrong function name', async () => {
1596
1869
  const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1597
1870
  const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1598
- const runner = openai.beta.chat.completions.runFunctions({
1871
+ const runner = openai.beta.chat.completions.runTools({
1599
1872
  stream: true,
1600
1873
  messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1601
1874
  model: 'gpt-3.5-turbo',
1602
- functions: [
1875
+ tools: [
1603
1876
  {
1604
- function: function getWeather() {
1605
- return `it's raining`;
1877
+ type: 'function',
1878
+ function: {
1879
+ function: function getWeather() {
1880
+ return `it's raining`;
1881
+ },
1882
+ parameters: {},
1883
+ description: 'gets the weather',
1606
1884
  },
1607
- parameters: {},
1608
- description: 'gets the weather',
1609
1885
  },
1610
1886
  ],
1611
1887
  });
@@ -1622,10 +1898,17 @@ describe('resource completions', () => {
1622
1898
  delta: {
1623
1899
  role: 'assistant',
1624
1900
  content: null,
1625
- function_call: {
1626
- arguments: '',
1627
- name: 'get_weather',
1628
- },
1901
+ tool_calls: [
1902
+ {
1903
+ type: 'function',
1904
+ index: 0,
1905
+ id: '123',
1906
+ function: {
1907
+ arguments: '',
1908
+ name: 'get_weather',
1909
+ },
1910
+ },
1911
+ ],
1629
1912
  },
1630
1913
  },
1631
1914
  ],
@@ -1640,15 +1923,21 @@ describe('resource completions', () => {
1640
1923
  {
1641
1924
  role: 'assistant',
1642
1925
  content: null,
1643
- function_call: {
1644
- arguments: '',
1645
- name: 'get_weather',
1646
- },
1926
+ tool_calls: [
1927
+ {
1928
+ type: 'function',
1929
+ id: '123',
1930
+ function: {
1931
+ arguments: '',
1932
+ name: 'get_weather',
1933
+ },
1934
+ },
1935
+ ],
1647
1936
  },
1648
1937
  {
1649
- role: 'function',
1650
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1651
- name: 'get_weather',
1938
+ role: 'tool',
1939
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1940
+ tool_call_id: '123',
1652
1941
  },
1653
1942
  ]);
1654
1943
  yield {
@@ -1660,10 +1949,17 @@ describe('resource completions', () => {
1660
1949
  delta: {
1661
1950
  role: 'assistant',
1662
1951
  content: null,
1663
- function_call: {
1664
- arguments: '',
1665
- name: 'getWeather',
1666
- },
1952
+ tool_calls: [
1953
+ {
1954
+ type: 'function',
1955
+ index: 0,
1956
+ id: '1234',
1957
+ function: {
1958
+ arguments: '',
1959
+ name: 'getWeather',
1960
+ },
1961
+ },
1962
+ ],
1667
1963
  },
1668
1964
  },
1669
1965
  ],
@@ -1678,28 +1974,40 @@ describe('resource completions', () => {
1678
1974
  {
1679
1975
  role: 'assistant',
1680
1976
  content: null,
1681
- function_call: {
1682
- arguments: '',
1683
- name: 'get_weather',
1684
- },
1977
+ tool_calls: [
1978
+ {
1979
+ type: 'function',
1980
+ id: '123',
1981
+ function: {
1982
+ arguments: '',
1983
+ name: 'get_weather',
1984
+ },
1985
+ },
1986
+ ],
1685
1987
  },
1686
1988
  {
1687
- role: 'function',
1688
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1689
- name: 'get_weather',
1989
+ role: 'tool',
1990
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
1991
+ tool_call_id: '123',
1690
1992
  },
1691
1993
  {
1692
1994
  role: 'assistant',
1693
1995
  content: null,
1694
- function_call: {
1695
- arguments: '',
1696
- name: 'getWeather',
1697
- },
1996
+ tool_calls: [
1997
+ {
1998
+ type: 'function',
1999
+ id: '1234',
2000
+ function: {
2001
+ arguments: '',
2002
+ name: 'getWeather',
2003
+ },
2004
+ },
2005
+ ],
1698
2006
  },
1699
2007
  {
1700
- role: 'function',
2008
+ role: 'tool',
1701
2009
  content: `it's raining`,
1702
- name: 'getWeather',
2010
+ tool_call_id: '1234',
1703
2011
  },
1704
2012
  ]);
1705
2013
  for (const choice of contentChoiceDeltas(`it's raining`)) {
@@ -1715,79 +2023,45 @@ describe('resource completions', () => {
1715
2023
  runner.done(),
1716
2024
  ]);
1717
2025
  expect(listener.eventMessages).toEqual([
1718
- { role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
1719
2026
  {
1720
- role: 'function',
1721
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1722
- name: 'get_weather',
2027
+ role: 'assistant',
2028
+ content: null,
2029
+ tool_calls: [
2030
+ {
2031
+ type: 'function',
2032
+ id: '123',
2033
+ function: {
2034
+ arguments: '',
2035
+ name: 'get_weather',
2036
+ },
2037
+ },
2038
+ ],
1723
2039
  },
1724
- { role: 'assistant', content: null, function_call: { name: 'getWeather', arguments: '' } },
1725
- { role: 'function', content: `it's raining`, name: 'getWeather' },
1726
- { role: 'assistant', content: "it's raining" },
1727
- ]);
1728
- expect(listener.eventFunctionCallResults).toEqual([
1729
- `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1730
- `it's raining`,
1731
- ]);
1732
- await listener.sanityCheck();
1733
- });
1734
- test('wrong function name with single function call', async () => {
1735
- const { fetch, handleRequest } = mockStreamingChatCompletionFetch();
1736
- const openai = new openai_1.default({ apiKey: 'something1234', baseURL: 'http://127.0.0.1:4010', fetch });
1737
- const runner = openai.beta.chat.completions.runFunctions({
1738
- stream: true,
1739
- messages: [{ role: 'user', content: 'tell me what the weather is like' }],
1740
- model: 'gpt-3.5-turbo',
1741
- function_call: {
1742
- name: 'getWeather',
2040
+ {
2041
+ role: 'tool',
2042
+ content: `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
2043
+ tool_call_id: '123',
1743
2044
  },
1744
- functions: [
1745
- {
1746
- function: function getWeather() {
1747
- return `it's raining`;
1748
- },
1749
- parameters: {},
1750
- description: 'gets the weather',
1751
- },
1752
- ],
1753
- });
1754
- const listener = new StreamingRunnerListener(runner);
1755
- await Promise.all([
1756
- handleRequest(async function* (request) {
1757
- expect(request.messages).toEqual([{ role: 'user', content: 'tell me what the weather is like' }]);
1758
- yield {
1759
- id: '1',
1760
- choices: [
1761
- {
1762
- index: 0,
1763
- finish_reason: 'function_call',
1764
- delta: {
1765
- role: 'assistant',
1766
- content: null,
1767
- function_call: {
1768
- arguments: '',
1769
- name: 'get_weather',
1770
- },
1771
- },
1772
- },
1773
- ],
1774
- created: Math.floor(Date.now() / 1000),
1775
- model: 'gpt-3.5-turbo',
1776
- object: 'chat.completion.chunk',
1777
- };
1778
- }),
1779
- runner.done(),
1780
- ]);
1781
- expect(listener.eventMessages).toEqual([
1782
- { role: 'assistant', content: null, function_call: { name: 'get_weather', arguments: '' } },
1783
2045
  {
1784
- role: 'function',
1785
- content: `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
1786
- name: 'get_weather',
2046
+ role: 'assistant',
2047
+ content: null,
2048
+ tool_calls: [
2049
+ {
2050
+ type: 'function',
2051
+ id: '1234',
2052
+ function: {
2053
+ arguments: '',
2054
+ name: 'getWeather',
2055
+ },
2056
+ },
2057
+ ],
1787
2058
  },
2059
+ { role: 'tool', content: `it's raining`, tool_call_id: '1234' },
2060
+ { role: 'assistant', content: "it's raining" },
1788
2061
  ]);
1789
2062
  expect(listener.eventFunctionCallResults).toEqual([
1790
- `Invalid function_call: "get_weather". Available options are: "getWeather". Please try again`,
2063
+ `Invalid tool_call: "get_weather". Available options are: "getWeather". Please try again`,
2064
+ `it's raining`,
1791
2065
  ]);
1792
2066
  await listener.sanityCheck();
1793
2067
  });