aimyapi 0.1.2 → 0.1.4
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/README.md +196 -4
- package/dist/{lib/index.d.ts → index.d.ts} +1 -1
- package/dist/{lib/index.js → index.js} +18 -16
- package/dist/{lib/sandbox.js → sandbox.js} +1 -1
- package/example/example1.ts +0 -2
- package/example/example2.ts +5 -7
- package/example/ordering_api.md +23 -11
- package/example/ordering_api.ts +8 -12
- package/example/ordering_api_impl.ts +30 -21
- package/lib/index.ts +18 -21
- package/lib/sandbox.ts +1 -1
- package/package.json +1 -1
- package/tsconfig.json +2 -2
- package/dist/example/example1.d.ts +0 -1
- package/dist/example/example1.js +0 -52
- package/dist/example/example2.d.ts +0 -1
- package/dist/example/example2.js +0 -66
- package/dist/example/example3.d.ts +0 -1
- package/dist/example/example3.js +0 -79
- package/dist/example/ordering_api.d.ts +0 -36
- package/dist/example/ordering_api.js +0 -125
- package/dist/example/ordering_api_impl.d.ts +0 -23
- package/dist/example/ordering_api_impl.js +0 -128
- package/dist/example/sales_api.d.ts +0 -16
- package/dist/example/sales_api.js +0 -5
- package/dist/example/sales_api_impl.d.ts +0 -7
- package/dist/example/sales_api_impl.js +0 -59
- /package/dist/{lib/sandbox-wrappers.d.ts → sandbox-wrappers.d.ts} +0 -0
- /package/dist/{lib/sandbox-wrappers.js → sandbox-wrappers.js} +0 -0
- /package/dist/{lib/sandbox.d.ts → sandbox.d.ts} +0 -0
- /package/dist/{lib/utils.d.ts → utils.d.ts} +0 -0
- /package/dist/{lib/utils.js → utils.js} +0 -0
package/README.md
CHANGED
|
@@ -152,26 +152,218 @@ The module created by the `createWithAPI` function:
|
|
|
152
152
|
|
|
153
153
|
#### Methods
|
|
154
154
|
|
|
155
|
-
- `generateCode(queryText: string, userChatHistory: ChatCompletionRequestMessage[]): Promise<string>`: A function that generates code for the given query text and user chat history.
|
|
156
|
-
- `runCode(task: string): Promise<void>`: A function that runs the generated code.
|
|
157
|
-
- `processRequest(userQuery: string, context?: object): Promise<string>`: A function that
|
|
155
|
+
- `generateCode(queryText: string, userChatHistory: ChatCompletionRequestMessage[]): Promise<string>`: A function that generates code to be run in the sandbox for the given query text and user chat history.
|
|
156
|
+
- `runCode(task: string): Promise<void>`: A function that runs the generated code in the sandbox.
|
|
157
|
+
- `processRequest(userQuery: string, context?: object): Promise<string>`: A single function that generates and runs code assuming no chat history.
|
|
158
158
|
|
|
159
159
|
## Examples
|
|
160
160
|
|
|
161
161
|
Download or clone the repo. From the root folder run the following.
|
|
162
162
|
|
|
163
|
+
|
|
164
|
+
### Example 1 - sales database
|
|
163
165
|
A simple api example where the LLM allows you to ask questions and compute things about a dataset
|
|
164
166
|
```
|
|
165
167
|
npm run example1
|
|
166
168
|
```
|
|
167
169
|
|
|
170
|
+
```
|
|
171
|
+
import AIMyAPI from "../lib";
|
|
172
|
+
import { API } from "./sales_api_impl";
|
|
173
|
+
import * as APIExports from "./sales_api";
|
|
174
|
+
import path from "path";
|
|
175
|
+
|
|
176
|
+
// Simpler example using no support for chat history;
|
|
177
|
+
|
|
178
|
+
(async () => {
|
|
179
|
+
const api = new API();
|
|
180
|
+
|
|
181
|
+
const aimyapi = await AIMyAPI.createWithAPI({
|
|
182
|
+
apiObject: api,
|
|
183
|
+
apiGlobalName: "api", // Should match whatever you declared as your global in your api.
|
|
184
|
+
apiExports: APIExports,
|
|
185
|
+
apiDefFilePath: path.join(__dirname, "./sales_api.ts"),
|
|
186
|
+
apiDocsPath: path.join(__dirname, "./sales_api.md"),
|
|
187
|
+
debug: false,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
console.log("Print 'hello' three times.")
|
|
191
|
+
await aimyapi.processRequest("Print 'hello' three times.");
|
|
192
|
+
|
|
193
|
+
console.log("What was our best month in 2020")
|
|
194
|
+
await aimyapi.processRequest("What was our best month in 2020");
|
|
195
|
+
|
|
196
|
+
console.log("Which business unit had the highest sales in 2020?")
|
|
197
|
+
await aimyapi.processRequest("Which business unit had the highest sales in 2020?");
|
|
198
|
+
|
|
199
|
+
console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
|
|
200
|
+
await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
|
|
201
|
+
})();
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Output:
|
|
205
|
+
```
|
|
206
|
+
Print 'hello' three times.
|
|
207
|
+
Generate Task: 4.086s
|
|
208
|
+
hello
|
|
209
|
+
hello
|
|
210
|
+
hello
|
|
211
|
+
Run Code: 379.328ms
|
|
212
|
+
What was our best month in 2020
|
|
213
|
+
Generate Task: 11.345s
|
|
214
|
+
Our best month in 2020 was month 8 with 4400 sales.
|
|
215
|
+
Run Code: 119.145ms
|
|
216
|
+
Which business unit had the highest sales in 2020?
|
|
217
|
+
Generate Task: 11.477s
|
|
218
|
+
The business unit with the highest sales in 2020 was Hardware
|
|
219
|
+
Run Code: 124.522ms
|
|
220
|
+
Compute the total sales for each month in 2020 then email the top 3 to test@email.com
|
|
221
|
+
Generate Task: 15.648s
|
|
222
|
+
Sending email to "test@email.com" with subject "Top 3 Sales Months in 2020" and body
|
|
223
|
+
"Top 3 sales months in 2020:
|
|
224
|
+
Month 8: $4400
|
|
225
|
+
Month 7: $4300
|
|
226
|
+
Month 6: $4000"
|
|
227
|
+
Run Code: 1.200s
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Example 2 - Food ordering bot
|
|
231
|
+
|
|
168
232
|
A more complex food ordering example which incorporates chat history
|
|
169
233
|
|
|
170
234
|
```
|
|
171
235
|
npm run example2
|
|
172
236
|
```
|
|
173
237
|
|
|
174
|
-
|
|
238
|
+
Code:
|
|
239
|
+
```
|
|
240
|
+
import AIMyAPI from "../lib";
|
|
241
|
+
import { OrderingAPI } from "./ordering_api_impl";
|
|
242
|
+
import * as APIExports from "./ordering_api";
|
|
243
|
+
import path from "path";
|
|
244
|
+
|
|
245
|
+
// More complex fast food ordering example that uses chat history.
|
|
246
|
+
// Fast food ordering example.
|
|
247
|
+
(async () => {
|
|
248
|
+
const api = new OrderingAPI();
|
|
249
|
+
|
|
250
|
+
const aimyapi = await AIMyAPI.createWithAPI({
|
|
251
|
+
apiObject: api,
|
|
252
|
+
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
253
|
+
apiExports: APIExports,
|
|
254
|
+
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
255
|
+
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
256
|
+
debug: false,
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
async function runQuery(query:string) {
|
|
260
|
+
console.log(`Query: ${query}`)
|
|
261
|
+
|
|
262
|
+
// generate the code for this query
|
|
263
|
+
const code = await aimyapi.generateCode(query, api._getHistory());
|
|
264
|
+
|
|
265
|
+
api._addMessageToHistory({
|
|
266
|
+
content: query,
|
|
267
|
+
role: "user",
|
|
268
|
+
name: "user",
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
api._addMessageToHistory({
|
|
272
|
+
content: '```\n' + code + '\n```',
|
|
273
|
+
role: "assistant",
|
|
274
|
+
name: "assistant",
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// run the code in the sandbox
|
|
278
|
+
await aimyapi.runCode(code);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
await runQuery("How's the burger here?");
|
|
282
|
+
await runQuery("I'd like a plain hamburger and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.");
|
|
283
|
+
await runQuery("I changed my mind, instead of anchovies, can I get a large gluten free pizza with pineapple instead.");
|
|
284
|
+
await runQuery("email me the total at myemail@test.com and complete the order");
|
|
285
|
+
|
|
286
|
+
})();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Output:
|
|
290
|
+
```
|
|
291
|
+
Query: How's the burger here?
|
|
292
|
+
Our Hamburger is delicious! It comes with cheese, lettuce, tomato, and onion by default, but you can customize it with any of our toppings.
|
|
293
|
+
Query: I'd like a plain hamburger (no cheese) and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.
|
|
294
|
+
added #0 Hamburger... $8.99
|
|
295
|
+
lettuce
|
|
296
|
+
tomato
|
|
297
|
+
onion
|
|
298
|
+
|
|
299
|
+
Ok, I added a plain hamburger. What else would you like?
|
|
300
|
+
added #1 Fries... $2.99
|
|
301
|
+
Large... $1.99
|
|
302
|
+
|
|
303
|
+
Ok, I added large fries. What else would you like?
|
|
304
|
+
added #2 Pizza... $10.99
|
|
305
|
+
anchovies
|
|
306
|
+
|
|
307
|
+
Ok, I added a pizza with anchovies. What else would you like?
|
|
308
|
+
added #3 Fountain Drink... $1.99
|
|
309
|
+
Large... $0.99
|
|
310
|
+
|
|
311
|
+
Ok, I added a cola. What else would you like?
|
|
312
|
+
added #4 Hamburger... $8.99
|
|
313
|
+
cheese
|
|
314
|
+
lettuce
|
|
315
|
+
tomato
|
|
316
|
+
onion
|
|
317
|
+
cheese
|
|
318
|
+
bacon
|
|
319
|
+
avocado
|
|
320
|
+
|
|
321
|
+
Ok, I added a cheese burger with bacon and avocado. Is there anything else I can help you with?
|
|
322
|
+
Query: I changed my mind, instead of anchovies, can I get a large gluten free pizza with pineapple instead.
|
|
323
|
+
Removed item 2
|
|
324
|
+
added #5 Pizza... $10.99
|
|
325
|
+
pineapple
|
|
326
|
+
Gluten Free Crust... $2.99
|
|
327
|
+
|
|
328
|
+
Ok, I added a large gluten free pizza with pineapple. Is there anything else I can help you with?
|
|
329
|
+
Query: email me the total at myemail@test.com and complete the order
|
|
330
|
+
Sending email to "myemail@test.com" with subject "Order Total" and body
|
|
331
|
+
"Your order total is $39.92."
|
|
332
|
+
----
|
|
333
|
+
|
|
334
|
+
Displaying order:
|
|
335
|
+
#0 Hamburger... $8.99
|
|
336
|
+
lettuce
|
|
337
|
+
tomato
|
|
338
|
+
onion
|
|
339
|
+
|
|
340
|
+
#1 Fries... $2.99
|
|
341
|
+
Large... $1.99
|
|
342
|
+
|
|
343
|
+
#3 Fountain Drink... $1.99
|
|
344
|
+
Large... $0.99
|
|
345
|
+
|
|
346
|
+
#4 Hamburger... $8.99
|
|
347
|
+
cheese
|
|
348
|
+
lettuce
|
|
349
|
+
tomato
|
|
350
|
+
onion
|
|
351
|
+
cheese
|
|
352
|
+
bacon
|
|
353
|
+
avocado
|
|
354
|
+
|
|
355
|
+
#5 Pizza... $10.99
|
|
356
|
+
pineapple
|
|
357
|
+
Gluten Free Crust... $2.99
|
|
358
|
+
|
|
359
|
+
-- Total: $39.92
|
|
360
|
+
Order completed!
|
|
361
|
+
Your order has been completed. Thank you for choosing our restaurant!
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
# Example 3 - interactive food ordering
|
|
365
|
+
|
|
366
|
+
Interactive ordering example (same api as example2). You can type your own orders on the command line.
|
|
175
367
|
|
|
176
368
|
```
|
|
177
369
|
npm run example3
|
|
@@ -19,7 +19,7 @@ export interface CreateWithAPIExports {
|
|
|
19
19
|
export interface AIMyAPIExports {
|
|
20
20
|
createWithAPI: (options: AIMyAPIOptions) => Promise<CreateWithAPIExports>;
|
|
21
21
|
createBasePrompt: (apiFilePath: string, documentationPath: string) => string;
|
|
22
|
-
|
|
22
|
+
generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug: boolean) => Promise<string>;
|
|
23
23
|
createSandbox: (QuickJS: QuickJSWASMModule, globals: any) => Promise<any>;
|
|
24
24
|
}
|
|
25
25
|
declare const aimyapi: AIMyAPIExports;
|
|
@@ -29,12 +29,24 @@ function createBasePrompt(apiFilePath, documentationPath) {
|
|
|
29
29
|
return createTaskPrompt;
|
|
30
30
|
}
|
|
31
31
|
exports.createBasePrompt = createBasePrompt;
|
|
32
|
-
//
|
|
32
|
+
// FIXME: add an options parameter and allow specifying the token limit
|
|
33
33
|
const generateCode = async function (queryText, userChatHistory, createTaskPrompt, apiPath, debug = false) {
|
|
34
34
|
if (!queryText)
|
|
35
35
|
return;
|
|
36
36
|
let generatedCode = '';
|
|
37
37
|
const prompt = createTaskPrompt.replace("{{QUERY_TEXT}}", queryText);
|
|
38
|
+
const messages = [
|
|
39
|
+
{
|
|
40
|
+
role: "system",
|
|
41
|
+
content: prompt,
|
|
42
|
+
},
|
|
43
|
+
...userChatHistory,
|
|
44
|
+
{
|
|
45
|
+
role: "user",
|
|
46
|
+
content: `${queryText}`,
|
|
47
|
+
name: "user"
|
|
48
|
+
}
|
|
49
|
+
];
|
|
38
50
|
// TODO: I should switch this back to gpt3.5 turbo since it's cheaper
|
|
39
51
|
try {
|
|
40
52
|
// const task = await openai.createCompletion(
|
|
@@ -47,20 +59,9 @@ const generateCode = async function (queryText, userChatHistory, createTaskPromp
|
|
|
47
59
|
// );
|
|
48
60
|
const results = await openai.createChatCompletion({
|
|
49
61
|
model: "gpt-3.5-turbo",
|
|
50
|
-
messages:
|
|
51
|
-
{
|
|
52
|
-
role: "system",
|
|
53
|
-
content: prompt,
|
|
54
|
-
},
|
|
55
|
-
...userChatHistory,
|
|
56
|
-
{
|
|
57
|
-
role: "user",
|
|
58
|
-
content: `${queryText}`,
|
|
59
|
-
name: "user"
|
|
60
|
-
}
|
|
61
|
-
],
|
|
62
|
+
messages: messages,
|
|
62
63
|
temperature: 0.1,
|
|
63
|
-
max_tokens:
|
|
64
|
+
max_tokens: 700,
|
|
64
65
|
});
|
|
65
66
|
if (debug)
|
|
66
67
|
console.log(results.data.usage);
|
|
@@ -73,11 +74,12 @@ const generateCode = async function (queryText, userChatHistory, createTaskPromp
|
|
|
73
74
|
if (codeStart === -1 || codeEnd === -1 || codeStart === codeEnd)
|
|
74
75
|
return '';
|
|
75
76
|
generatedCode = response.substring(codeStart + 3, codeEnd).replace('typescript', '');
|
|
76
|
-
generatedCode =
|
|
77
|
+
generatedCode = generatedCode.replace("./api.ts", apiPath);
|
|
77
78
|
return generatedCode;
|
|
78
79
|
}
|
|
79
80
|
catch (err) {
|
|
80
81
|
console.error(err);
|
|
82
|
+
console.log("Prompt", messages);
|
|
81
83
|
return '';
|
|
82
84
|
}
|
|
83
85
|
};
|
|
@@ -173,7 +175,7 @@ const aimyapi = {
|
|
|
173
175
|
createWithAPI,
|
|
174
176
|
// functions for customized usage
|
|
175
177
|
createBasePrompt,
|
|
176
|
-
|
|
178
|
+
generateCode: exports.generateCode,
|
|
177
179
|
createSandbox: sandbox_1.default,
|
|
178
180
|
};
|
|
179
181
|
exports.default = aimyapi;
|
|
@@ -121,7 +121,7 @@ async function createSandbox(QuickJS, requireLookup = {}, globals = {}, debug =
|
|
|
121
121
|
try {
|
|
122
122
|
const compiled = tsCompile(task);
|
|
123
123
|
if (!compiled || compiled.length === 0) {
|
|
124
|
-
console.
|
|
124
|
+
console.error("Could not compile", task);
|
|
125
125
|
return false;
|
|
126
126
|
}
|
|
127
127
|
// View compiled typescript code for debugging
|
package/example/example1.ts
CHANGED
package/example/example2.ts
CHANGED
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
|
|
2
1
|
import AIMyAPI from "../lib";
|
|
3
2
|
import { OrderingAPI } from "./ordering_api_impl";
|
|
4
3
|
import * as APIExports from "./ordering_api";
|
|
5
4
|
import path from "path";
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
6
|
// More complex fast food ordering example that uses chat history.
|
|
10
7
|
// Fast food ordering example.
|
|
11
8
|
(async () => {
|
|
12
9
|
const api = new OrderingAPI();
|
|
13
10
|
|
|
14
|
-
const
|
|
11
|
+
const options = {
|
|
15
12
|
apiObject: api,
|
|
16
13
|
apiGlobalName: "orderingApi", // Should match whatever you declared as your global in your ordering api.
|
|
17
14
|
apiExports: APIExports,
|
|
18
15
|
apiDefFilePath: path.join(__dirname, "./ordering_api.ts"),
|
|
19
16
|
apiDocsPath: path.join(__dirname, "./ordering_api.md"),
|
|
20
17
|
debug: false,
|
|
21
|
-
}
|
|
18
|
+
};
|
|
19
|
+
const aimyapi = await AIMyAPI.createWithAPI(options)
|
|
22
20
|
|
|
23
21
|
async function runQuery(query:string) {
|
|
24
22
|
console.log(`Query: ${query}`)
|
|
@@ -33,7 +31,7 @@ import path from "path";
|
|
|
33
31
|
});
|
|
34
32
|
|
|
35
33
|
api._addMessageToHistory({
|
|
36
|
-
content: '```\n' + code + '\n```',
|
|
34
|
+
content: '```\n' + code.replace(options.apiDefFilePath, "./api.ts") + '\n```',
|
|
37
35
|
role: "assistant",
|
|
38
36
|
name: "assistant",
|
|
39
37
|
});
|
|
@@ -43,7 +41,7 @@ import path from "path";
|
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
await runQuery("How's the burger here?");
|
|
46
|
-
await runQuery("I'd like a plain hamburger and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.");
|
|
44
|
+
await runQuery("I'd like a plain hamburger (no cheese) and a large fries, a pizza with anchovies and a cola. I'd also like a cheese burger with bacon and avocado.");
|
|
47
45
|
await runQuery("I changed my mind, instead of anchovies, can I get a large gluten free pizza with pineapple instead.");
|
|
48
46
|
await runQuery("email me the total at myemail@test.com and complete the order");
|
|
49
47
|
|
package/example/ordering_api.md
CHANGED
|
@@ -20,14 +20,20 @@ import * as ApiDefs from './api.ts'
|
|
|
20
20
|
})();
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
user: Add a hamburger to my order
|
|
23
|
+
user: Add a hamburger with no cheese to my order
|
|
24
24
|
|
|
25
25
|
assistant:
|
|
26
26
|
```
|
|
27
27
|
import * as ApiDefs from './api.ts'
|
|
28
28
|
(async() {
|
|
29
29
|
try {
|
|
30
|
-
|
|
30
|
+
const itemName = "Hamburger";
|
|
31
|
+
const item = ApiDefs.Menu.find((item) => item.name === itemName);
|
|
32
|
+
if (!item) {
|
|
33
|
+
throw new Error(`Item with name "${itemName}" not found`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
orderingApi.addItemToOrder(itemName, undefined, item.toppings.filter( topping => topping.name != "cheese") );
|
|
31
37
|
orderingApi.respondToUser("Ok, I added a Hamburger. What else would you like?");
|
|
32
38
|
} catch(e) {
|
|
33
39
|
console.error(e);
|
|
@@ -35,6 +41,8 @@ import * as ApiDefs from './api.ts'
|
|
|
35
41
|
})();
|
|
36
42
|
```
|
|
37
43
|
|
|
44
|
+
assistant: Added Hamburger with id 1
|
|
45
|
+
|
|
38
46
|
user: I'd like a large pizza with mushrooms
|
|
39
47
|
|
|
40
48
|
assistant:
|
|
@@ -42,7 +50,6 @@ assistant:
|
|
|
42
50
|
import * as ApiDefs from './api.ts'
|
|
43
51
|
(async() {
|
|
44
52
|
try {
|
|
45
|
-
ApiDefs.Menu
|
|
46
53
|
orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
|
|
47
54
|
orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
|
|
48
55
|
} catch(err) {
|
|
@@ -51,23 +58,28 @@ import * as ApiDefs from './api.ts'
|
|
|
51
58
|
})();
|
|
52
59
|
```
|
|
53
60
|
|
|
54
|
-
user:
|
|
61
|
+
user: Add a hamburger with bacon
|
|
55
62
|
|
|
56
|
-
assistant:
|
|
63
|
+
assistant:
|
|
57
64
|
```
|
|
58
65
|
import * as ApiDefs from './api.ts'
|
|
59
66
|
(async() {
|
|
60
67
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
const itemName = "Hamburger";
|
|
69
|
+
const item = ApiDefs.Menu.find((item) => item.name === itemName);
|
|
70
|
+
if (!item) {
|
|
71
|
+
throw new Error(`Item with name "${itemName}" not found`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
orderingApi.addItemToOrder(itemName, undefined, [...item.toppings, "bacon"]);
|
|
75
|
+
orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
|
|
63
76
|
} catch(e) {
|
|
64
|
-
orderingApi.respondToUser("Apologies, something went wrong with that request.");
|
|
65
77
|
console.error(e);
|
|
66
78
|
}
|
|
67
79
|
})();
|
|
68
80
|
```
|
|
69
81
|
|
|
70
|
-
assistant: Added Hamburger with id
|
|
82
|
+
assistant: Added Hamburger with id 2
|
|
71
83
|
|
|
72
84
|
user: Add jalapenos to that
|
|
73
85
|
|
|
@@ -76,10 +88,10 @@ assistant:
|
|
|
76
88
|
import * as ApiDefs from './api.ts'
|
|
77
89
|
(async() {
|
|
78
90
|
try {
|
|
79
|
-
const existingItem = orderingApi.getItemInOrder("
|
|
91
|
+
const existingItem = orderingApi.getItemInOrder("2");
|
|
80
92
|
|
|
81
93
|
if(existingItem) {
|
|
82
|
-
orderingApi.modifyItemInOrder("
|
|
94
|
+
orderingApi.modifyItemInOrder("2", existingItem.customizations.map(item => item.name), [...existingItem.toppings, "jalapenos"]);
|
|
83
95
|
orderingApi.respondToUser("Ok, I added jalapenos to your Hamburger");
|
|
84
96
|
} else {
|
|
85
97
|
orderingApi.respondToUser("Hmm, I can't find that item.");
|
package/example/ordering_api.ts
CHANGED
|
@@ -66,20 +66,15 @@ export const Menu: MenuItemBase[] = [
|
|
|
66
66
|
{
|
|
67
67
|
"name": "Hamburger",
|
|
68
68
|
"price": 8.99,
|
|
69
|
-
"description": "A classic american hamburger with your choice of toppings. Cheese, lettuce, tomato, and onion are included by default. Other toppings available on request.",
|
|
69
|
+
"description": "A classic american hamburger with your choice of toppings. Cheese, lettuce, tomato, and onion toppings are included by default. Other toppings available on request.",
|
|
70
70
|
"category": "Burgers",
|
|
71
71
|
"tags": [
|
|
72
72
|
"hamburger",
|
|
73
73
|
"burger"
|
|
74
74
|
],
|
|
75
75
|
"customizations": [],
|
|
76
|
-
"allowedCustomizations": [
|
|
77
|
-
|
|
78
|
-
"name": "Special sauce",
|
|
79
|
-
"priceAdjustment": 1.99
|
|
80
|
-
}
|
|
81
|
-
],
|
|
82
|
-
"toppings": [],
|
|
76
|
+
"allowedCustomizations": [],
|
|
77
|
+
"toppings": [ "cheese", "lettuce", "tomato", "onion"],
|
|
83
78
|
"allowedToppings": [
|
|
84
79
|
"cheese",
|
|
85
80
|
"lettuce",
|
|
@@ -116,7 +111,7 @@ export const Menu: MenuItemBase[] = [
|
|
|
116
111
|
{
|
|
117
112
|
"name": "Fountain Drink",
|
|
118
113
|
"price": 1.99,
|
|
119
|
-
"description": "A classic fountain drink. Choose from Cola, Diet Cola, Dr. Dazzle, or Mountain Rush.",
|
|
114
|
+
"description": "A classic fountain drink. Choose from the following sodas Cola, Diet Cola, Dr. Dazzle, or Mountain Rush. Large size available on request.",
|
|
120
115
|
"category": "Drinks",
|
|
121
116
|
"tags": [
|
|
122
117
|
"drink",
|
|
@@ -157,9 +152,9 @@ export interface OrderingAPIInterface {
|
|
|
157
152
|
// Gets the customization with the specified name for the specified item.
|
|
158
153
|
// If the item does not have a customization with the specified name, returns undefined.
|
|
159
154
|
|
|
160
|
-
addItemToOrder(itemName:string, customizationNames: string[], toppings: string[]): void;
|
|
155
|
+
addItemToOrder(itemName:string, customizationNames: string[] | undefined, toppings: string[] | undefined): void;
|
|
161
156
|
// Adds the specified item to the order.
|
|
162
|
-
//
|
|
157
|
+
// leave customizationNames and toppings undefined if you want to use the default values for the item.
|
|
163
158
|
|
|
164
159
|
removeItemFromOrder(itemOrderId: string): void;
|
|
165
160
|
// Removes the item with the specified id from the order.
|
|
@@ -179,8 +174,9 @@ export interface OrderingAPIInterface {
|
|
|
179
174
|
delay(milliseconds: number): Promise<void>;
|
|
180
175
|
// waits for the specified number of milliseconds before resolving the promise.
|
|
181
176
|
|
|
182
|
-
displayItem(item: MenuItemBase): void;
|
|
177
|
+
displayItem(item: MenuItemBase, justAdded:boolean): void;
|
|
183
178
|
// Displays the specified item to the user.
|
|
179
|
+
// If justAdded is true, the item will be displayed as a new item in the order.
|
|
184
180
|
|
|
185
181
|
displayOrder(): void;
|
|
186
182
|
// Displays the current order to the user.
|
|
@@ -26,10 +26,7 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
26
26
|
|
|
27
27
|
respondToUser(text: string): void {
|
|
28
28
|
console.log(text);
|
|
29
|
-
|
|
30
|
-
role: "assistant",
|
|
31
|
-
content: "Response output: " + text,
|
|
32
|
-
});
|
|
29
|
+
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
delay(milliseconds: number): Promise<void> {
|
|
@@ -61,33 +58,38 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
61
58
|
|
|
62
59
|
addItemToOrder(
|
|
63
60
|
itemName: string,
|
|
64
|
-
customizationNames: string[],
|
|
65
|
-
toppings: string[]
|
|
61
|
+
customizationNames: string[] | undefined,
|
|
62
|
+
toppings: string[] | undefined
|
|
66
63
|
) {
|
|
67
64
|
const item = Menu.find((item) => item.name === itemName);
|
|
68
65
|
if (!item) {
|
|
69
66
|
throw new Error(`Item with name "${itemName}" not found`);
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
const customizations = customizationNames
|
|
69
|
+
const customizations = customizationNames ? customizationNames
|
|
73
70
|
.map((customizationName) => {
|
|
74
71
|
return this.getCustomizationByName(itemName, customizationName);
|
|
75
72
|
})
|
|
76
73
|
.filter(
|
|
77
74
|
(customization) => customization !== undefined
|
|
78
|
-
) as Customization[];
|
|
75
|
+
) as Customization[] : [...item.customizations];
|
|
79
76
|
|
|
80
77
|
const newItem = {
|
|
81
78
|
...item,
|
|
82
79
|
customizations,
|
|
83
|
-
toppings: toppings,
|
|
80
|
+
toppings: toppings ? toppings : [...item.toppings],
|
|
84
81
|
orderId: "" + this._lastOrderIdNumber++,
|
|
85
82
|
};
|
|
86
83
|
|
|
87
84
|
this._order.push(newItem);
|
|
88
85
|
|
|
89
|
-
this.respondToUser(`Added ${itemName} with id ${newItem.orderId}`);
|
|
90
|
-
|
|
86
|
+
//this.respondToUser(`Added ${itemName} with id ${newItem.orderId}`);
|
|
87
|
+
|
|
88
|
+
this._history.push({
|
|
89
|
+
role: "user",
|
|
90
|
+
content: `I see you have added added ${itemName} with id ${newItem.orderId}`,
|
|
91
|
+
});
|
|
92
|
+
this.displayItem(newItem, true);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
getItemInOrder(itemOrderId: string): MenuItemBase {
|
|
@@ -102,6 +104,10 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
102
104
|
removeItemFromOrder(itemOrderId: string) {
|
|
103
105
|
this._order = this._order.filter((item) => item.orderId !== itemOrderId);
|
|
104
106
|
|
|
107
|
+
this._history.push({
|
|
108
|
+
role: "user",
|
|
109
|
+
content: `I see you have removed item ${itemOrderId}`,
|
|
110
|
+
});
|
|
105
111
|
this.respondToUser(`Removed item ${itemOrderId}`);
|
|
106
112
|
}
|
|
107
113
|
|
|
@@ -132,6 +138,10 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
132
138
|
throw new Error(`Item with id #"${itemOrderId}" not found in order`);
|
|
133
139
|
}
|
|
134
140
|
|
|
141
|
+
this._history.push({
|
|
142
|
+
role: "user",
|
|
143
|
+
content: `I see you have modified item ${itemOrderId}`,
|
|
144
|
+
});
|
|
135
145
|
this.respondToUser(`Modified item ${itemOrderId}`);
|
|
136
146
|
}
|
|
137
147
|
|
|
@@ -160,20 +170,19 @@ export class OrderingAPI implements OrderingAPIInterface {
|
|
|
160
170
|
this._isCompleted = true;
|
|
161
171
|
}
|
|
162
172
|
|
|
163
|
-
displayItem(item: MenuItemBase) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
173
|
+
displayItem(item: MenuItemBase, justAdded: boolean = false) {
|
|
174
|
+
let output = "";
|
|
175
|
+
|
|
176
|
+
output += `\t${justAdded ? "added " : ""}#${item.orderId || ""} ${item.name}...\t\t$${item.price.toFixed(2)}\n`;
|
|
167
177
|
item.toppings.forEach((topping) => {
|
|
168
|
-
|
|
178
|
+
output += `\t\t${topping}\n`;
|
|
169
179
|
});
|
|
170
180
|
item.customizations.forEach((customization) => {
|
|
171
|
-
|
|
172
|
-
`\t\t${customization.name}...\t$${customization.priceAdjustment.toFixed(
|
|
173
|
-
2
|
|
174
|
-
)}`
|
|
175
|
-
);
|
|
181
|
+
output += `\t\t${customization.name}...\t$${customization.priceAdjustment.toFixed(2)}\n`;
|
|
176
182
|
});
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
this.respondToUser(output)
|
|
177
186
|
}
|
|
178
187
|
|
|
179
188
|
displayOrder() {
|