Skip to content

Commit 1ff1f13

Browse files
committed
test: $defs and $ref usage
1 parent a31c6c5 commit 1ff1f13

File tree

3 files changed

+215
-12
lines changed

3 files changed

+215
-12
lines changed

test/modelDependent/qwen3-0.6b/functions.test.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,132 @@ describe("qwen3 0.6b", () => {
119119

120120
expect(res2.length).to.be.greaterThan(1);
121121
});
122+
123+
test("$defs and $ref with recursion", {timeout: 1000 * 60 * 60 * 2}, async () => {
124+
const modelPath = await getModelFile("Qwen3-0.6B-Q8_0.gguf");
125+
const llama = await getTestLlama();
126+
127+
const model = await llama.loadModel({
128+
modelPath
129+
});
130+
const context = await model.createContext({
131+
contextSize: 1024
132+
});
133+
const chatSession = new LlamaChatSession({
134+
contextSequence: context.getSequence()
135+
});
136+
expect(chatSession.chatWrapper).to.be.instanceof(QwenChatWrapper);
137+
138+
const promptOptions = {
139+
functions: {
140+
getNthWord: defineChatSessionFunction({
141+
description: "Get an n-th word",
142+
params: {
143+
type: "object",
144+
$defs: {
145+
nthWord: {
146+
enum: [1, 2, 3, 4]
147+
}
148+
},
149+
properties: {
150+
n: {
151+
$ref: "#/$defs/nthWord"
152+
}
153+
}
154+
},
155+
handler(params) {
156+
return ["very", "secret", "this", "hello"][params.n - 1];
157+
}
158+
}),
159+
notifyOwner: defineChatSessionFunction({
160+
description: "Send a notification to the owner, and create sub notifications",
161+
params: {
162+
$ref: "#/$defs/notification",
163+
$defs: {
164+
notification: {
165+
type: "object",
166+
properties: {
167+
message: {
168+
type: "string"
169+
},
170+
subNotifications: {
171+
type: "array",
172+
items: {
173+
$ref: "#/$defs/notification"
174+
}
175+
}
176+
}
177+
}
178+
}
179+
},
180+
handler(notification) {
181+
createdNotifications.push(notification);
182+
return "Notification created";
183+
}
184+
})
185+
}
186+
} as const satisfies Parameters<typeof chatSession.prompt>[1];
187+
const createdNotifications: Parameters<typeof promptOptions["functions"]["notifyOwner"]["handler"]>[0][] = [];
188+
189+
const res = await chatSession.prompt("What is the second word? No yapping, no formatting", {
190+
...promptOptions,
191+
maxTokens: 250,
192+
budgets: {
193+
thoughtTokens: 100
194+
}
195+
});
196+
197+
expect(res.trim()).to.be.eq('The second word is "secret".');
198+
199+
const res2 = await chatSession.prompt([
200+
"The owner has 3 apps: App1, App2, and App3.",
201+
"Notify the owner with a main notifications about 'apps time', with sub notifications for each app with the app's name.",
202+
"Under each app sub-notification add a sub-notification with the app's number."
203+
].join("\n"), {
204+
...promptOptions,
205+
maxTokens: 200,
206+
budgets: {
207+
thoughtTokens: 0
208+
}
209+
});
210+
211+
expect(res2.length).to.be.greaterThan(1);
212+
expect(createdNotifications).toMatchInlineSnapshot(`
213+
[
214+
{
215+
"message": "apps time",
216+
"subNotifications": [
217+
{
218+
"message": "App1",
219+
"subNotifications": [
220+
{
221+
"message": "1. App1 sub notification 1",
222+
"subNotifications": [],
223+
},
224+
],
225+
},
226+
{
227+
"message": "App2",
228+
"subNotifications": [
229+
{
230+
"message": "2. App2 sub notification 2",
231+
"subNotifications": [],
232+
},
233+
],
234+
},
235+
{
236+
"message": "App3",
237+
"subNotifications": [
238+
{
239+
"message": "3. App3 sub notification 3",
240+
"subNotifications": [],
241+
},
242+
],
243+
},
244+
],
245+
},
246+
]
247+
`);
248+
});
122249
});
123250
});

test/standalone/chatWrappers/FunctionaryChatWrapper.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,58 @@ describe("FunctionaryChatWrapper", () => {
3939
return Math.floor(Math.random() * (params.max - params.min + 1) + params.min);
4040
}
4141
}),
42+
notifyOwner: defineChatSessionFunction({
43+
description: "Send a notification to the owner, and create sub notifications",
44+
params: {
45+
$ref: "#/$defs/notification",
46+
$defs: {
47+
notification: {
48+
type: "object",
49+
properties: {
50+
message: {
51+
type: "string"
52+
},
53+
subNotifications: {
54+
type: "array",
55+
items: {
56+
$ref: "#/$defs/notification"
57+
}
58+
}
59+
}
60+
}
61+
}
62+
},
63+
handler(notification) {
64+
return "Notification created: " + notification.message;
65+
}
66+
}),
67+
notifyOwner2: defineChatSessionFunction({
68+
description: "Send a notification to the owner, and create sub notifications",
69+
params: {
70+
$ref: "#/$defs/notification",
71+
$defs: {
72+
notification: {
73+
type: "object",
74+
properties: {
75+
message: {
76+
type: "string",
77+
description: "Notification message"
78+
},
79+
subNotifications: {
80+
type: "array",
81+
description: "Sub notifications",
82+
items: {
83+
$ref: "#/$defs/notification"
84+
}
85+
}
86+
}
87+
}
88+
}
89+
},
90+
handler(notification) {
91+
return "Notification created: " + notification.message;
92+
}
93+
}),
4294
func1: defineChatSessionFunction({
4395
description: "Some function",
4496
params: {
@@ -188,6 +240,18 @@ describe("FunctionaryChatWrapper", () => {
188240
// Get a random number
189241
type getRandomNumber = (_: {min: number, max: number}) => any;
190242
243+
// Send a notification to the owner, and create sub notifications
244+
type notifyOwner = (_: /* Type: notification */ {message: string, subNotifications: (/* notification type */ any)[]}) => any;
245+
246+
// Send a notification to the owner, and create sub notifications
247+
type notifyOwner2 = (_: /* Type: notification */ {
248+
// Notification message
249+
message: string,
250+
251+
// Sub notifications
252+
subNotifications: (/* notification type */ any)[]
253+
}) => any;
254+
191255
// Some function
192256
type func1 = (_: {
193257
// Some message
@@ -403,6 +467,18 @@ describe("FunctionaryChatWrapper", () => {
403467
// Get a random number
404468
type getRandomNumber = (_: {min: number, max: number}) => any;
405469
470+
// Send a notification to the owner, and create sub notifications
471+
type notifyOwner = (_: /* Type: notification */ {message: string, subNotifications: (/* notification type */ any)[]}) => any;
472+
473+
// Send a notification to the owner, and create sub notifications
474+
type notifyOwner2 = (_: /* Type: notification */ {
475+
// Notification message
476+
message: string,
477+
478+
// Sub notifications
479+
subNotifications: (/* notification type */ any)[]
480+
}) => any;
481+
406482
// Some function
407483
type func1 = (_: {
408484
// Some message

test/standalone/llamaEvaluator/LlamaGrammar.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,22 +2373,21 @@ describe("grammar for JSON schema", () => {
23732373
};
23742374

23752375
expect(grammar.grammar).toMatchInlineSnapshot(`
2376-
"root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? def0 comma-whitespace-b-1-4-rule "\\"numberOfWordsInMessage\\"" ":" [ ]? def1 comma-whitespace-b-1-4-rule "\\"feelingGoodPercentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule "\\"feelingGood\\"" ":" [ ]? def2 comma-whitespace-b-1-4-rule "\\"feelingOverall\\"" ":" [ ]? def2 comma-whitespace-b-1-4-rule "\\"verbsInMessage\\"" ":" [ ]? rule0 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]*
2376+
"root ::= "{" whitespace-b-1-4-rule "\\"message\\"" ":" [ ]? rule0 comma-whitespace-b-1-4-rule "\\"numberOfWordsInMessage\\"" ":" [ ]? integer-number-rule comma-whitespace-b-1-4-rule "\\"feelingGoodPercentage\\"" ":" [ ]? fractional-number-rule comma-whitespace-b-1-4-rule "\\"feelingGood\\"" ":" [ ]? rule1 comma-whitespace-b-1-4-rule "\\"feelingOverall\\"" ":" [ ]? rule1 comma-whitespace-b-1-4-rule "\\"verbsInMessage\\"" ":" [ ]? rule2 whitespace-b-0-4-rule "}" "\\n\\n\\n\\n" [\\n]*
23772377
string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4}
23782378
string-rule ::= "\\"" string-char-rule* "\\""
23792379
null-rule ::= "null"
2380-
def0 ::= ( string-rule | null-rule )
2380+
rule0 ::= ( string-rule | null-rule )
23812381
comma-whitespace-b-1-4-rule ::= "," ([\\n] (" " | "\\t") | [ ]?)
23822382
integer-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))?
2383-
def1 ::= integer-number-rule
23842383
fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))?
2385-
def3 ::= "\\"good\\""
2386-
def4 ::= "\\"bad\\""
2387-
def2 ::= ( def3 | def4 )
2384+
val0 ::= "\\"good\\""
2385+
val1 ::= "\\"bad\\""
2386+
rule1 ::= ( val0 | val1 )
23882387
comma-whitespace-b-2-4-rule ::= "," ([\\n] (" "{8} | "\\t\\t") | [ ]?)
23892388
whitespace-b-2-4-rule ::= [\\n] (" "{8} | "\\t\\t") | [ ]?
23902389
whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]?
2391-
rule0 ::= "[" whitespace-b-2-4-rule ( string-rule ( comma-whitespace-b-2-4-rule string-rule )* )? whitespace-b-1-4-rule "]"
2390+
rule2 ::= "[" whitespace-b-2-4-rule ( string-rule ( comma-whitespace-b-2-4-rule string-rule )* )? whitespace-b-1-4-rule "]"
23922391
whitespace-b-0-4-rule ::= [\\n] | [ ]?"
23932392
`);
23942393

@@ -2576,14 +2575,15 @@ describe("grammar for JSON schema", () => {
25762575
string-char-rule ::= [^"\\\\\\x7F\\x00-\\x1F] | "\\\\" ["\\\\/bfnrt] | "\\\\u" [0-9a-fA-F]{4}
25772576
string-rule ::= "\\"" string-char-rule* "\\""
25782577
fractional-number-rule ::= "-"? ("0" | [1-9] [0-9]{0,15}) ("." [0-9]{1,16})? ([eE] [-+]? ("0" | [1-9] [0-9]{0,15}))?
2579-
def2 ::= "\\"good\\""
2580-
def3 ::= "\\"bad\\""
2581-
rule0 ::= ( def2 | def3 )
2578+
val0 ::= "\\"good\\""
2579+
val1 ::= "\\"bad\\""
2580+
rule0 ::= ( val0 | val1 )
25822581
comma-whitespace-no-new-lines-rule ::= "," [ ]?
25832582
whitespace-no-new-lines-rule ::= [ ]?
25842583
rule1 ::= "{" whitespace-no-new-lines-rule "\\"feel\\"" ":" [ ]? rule0 comma-whitespace-no-new-lines-rule "\\"message\\"" ":" [ ]? def0 whitespace-no-new-lines-rule "}"
2585-
def1 ::= ( def2 | def3 | rule1 )
2586-
def0 ::= ( string-rule | fractional-number-rule | def1 )
2584+
rule2 ::= ( val0 | val1 | rule1 )
2585+
rule3 ::= ( string-rule | fractional-number-rule | rule2 )
2586+
def0 ::= rule3
25872587
whitespace-b-1-4-rule ::= [\\n] (" " | "\\t") | [ ]?
25882588
whitespace-b-0-4-rule ::= [\\n] | [ ]?"
25892589
`);

0 commit comments

Comments
 (0)