Skip to content

Commit 1ab24fe

Browse files
authored
feat: support anyOf in function parameters (#13)
1 parent 5873db7 commit 1ab24fe

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

src/functions.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@ interface ObjectProp {
1919
required?: string[];
2020
}
2121

22+
interface AnyOfProp {
23+
anyOf: Prop[];
24+
}
25+
2226
type Prop = {
2327
description?: string;
2428
} & (
29+
| AnyOfProp
2530
| ObjectProp
2631
| {
2732
type: "string";
@@ -41,6 +46,13 @@ type Prop = {
4146
}
4247
);
4348

49+
function isAnyOfProp(prop: Prop): prop is AnyOfProp {
50+
return (
51+
(prop as AnyOfProp).anyOf !== undefined &&
52+
Array.isArray((prop as AnyOfProp).anyOf)
53+
);
54+
}
55+
4456
// When OpenAI use functions in the prompt, they format them as TypeScript definitions rather than OpenAPI JSON schemas.
4557
// This function converts the JSON schemas into TypeScript definitions.
4658
export function formatFunctionDefinitions(functions: FunctionDef[]) {
@@ -80,6 +92,9 @@ function formatObjectProperties(obj: ObjectProp, indent: number): string {
8092

8193
// Format a single property type
8294
function formatType(param: Prop, indent: number): string {
95+
if (isAnyOfProp(param)) {
96+
return param.anyOf.map((v) => formatType(v, indent)).join(" | ");
97+
}
8398
switch (param.type) {
8499
case "string":
85100
if (param.enum) {

tests/token-counts.test.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,160 @@ const TEST_CASES: Example[] = [
264264
],
265265
tokens: 25,
266266
},
267+
{
268+
messages: [
269+
{
270+
role: "system",
271+
content: "You are an AI assistant trained to foo or bar",
272+
},
273+
{ role: "user", content: "My name is suzie" },
274+
{
275+
role: "function",
276+
name: "foo",
277+
content: '{"res":{"kind":"user","name":"suzie"}}',
278+
},
279+
{
280+
role: "user",
281+
content: 'I want to post a message with the text "hello world"',
282+
},
283+
{
284+
role: "function",
285+
name: "foo",
286+
content: '{"res":{"kind":"post","text":"hello world"}}',
287+
},
288+
],
289+
functions: [
290+
{
291+
name: "foo",
292+
description: "Return the foo or the bar",
293+
parameters: {
294+
type: "object",
295+
properties: {
296+
res: {
297+
anyOf: [
298+
{
299+
type: "object",
300+
properties: {
301+
kind: { type: "string", const: "post" },
302+
text: { type: "string" },
303+
},
304+
required: ["kind", "text"],
305+
additionalProperties: false,
306+
},
307+
{
308+
type: "object",
309+
properties: {
310+
kind: { type: "string", const: "user" },
311+
name: {
312+
type: "string",
313+
enum: ["jane", "suzie", "adam"],
314+
},
315+
},
316+
required: ["kind", "name"],
317+
additionalProperties: false,
318+
},
319+
],
320+
description: "The foo or the bar",
321+
},
322+
},
323+
required: ["res"],
324+
additionalProperties: false,
325+
},
326+
},
327+
],
328+
function_call: { name: "foo" },
329+
tokens: 158,
330+
},
331+
{
332+
messages: [
333+
{ role: "system", content: "Hello" },
334+
{ role: "user", content: "Hi there" },
335+
],
336+
functions: [
337+
{
338+
name: "do_stuff",
339+
parameters: {
340+
type: "object",
341+
properties: {
342+
foo: {
343+
anyOf: [
344+
{
345+
type: "object",
346+
properties: {
347+
kind: { type: "string", const: "a" },
348+
baz: { type: "boolean" },
349+
},
350+
},
351+
],
352+
},
353+
},
354+
},
355+
},
356+
],
357+
tokens: 52,
358+
},
359+
{
360+
messages: [
361+
{ role: "system", content: "Hello" },
362+
{ role: "user", content: "Hi there" },
363+
],
364+
functions: [
365+
{
366+
name: "do_stuff",
367+
parameters: {
368+
type: "object",
369+
properties: {
370+
foo: {
371+
anyOf: [
372+
{
373+
type: "object",
374+
properties: {
375+
kind: { type: "string", const: "a" },
376+
baz: { type: "boolean" },
377+
},
378+
},
379+
{
380+
type: "object",
381+
properties: {
382+
kind: { type: "string", const: "b" },
383+
qux: { type: "number" },
384+
},
385+
},
386+
{
387+
type: "object",
388+
properties: {
389+
kind: { type: "string", const: "c" },
390+
idk: { type: "string" },
391+
},
392+
},
393+
],
394+
},
395+
},
396+
},
397+
},
398+
],
399+
tokens: 80,
400+
},
401+
{
402+
messages: [
403+
{ role: "system", content: "Hello" },
404+
{ role: "user", content: "Hi there" },
405+
],
406+
functions: [
407+
{
408+
name: "do_stuff",
409+
parameters: {
410+
type: "object",
411+
properties: {
412+
foo: {
413+
anyOf: [{ type: "string", const: "a" }, { type: "number" }],
414+
},
415+
},
416+
},
417+
},
418+
],
419+
tokens: 44,
420+
},
267421
{
268422
messages: [
269423
{ role: "system", content: "Hello" },

0 commit comments

Comments
 (0)