aimyapi 0.1.9 → 0.1.11

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 CHANGED
@@ -264,7 +264,7 @@ import path from "path";
264
264
  console.log(`Query: ${query}`)
265
265
 
266
266
  // generate the code for this query
267
- const code = await aimyapi.generateCode(query, api._getHistory());
267
+ const codeResult = await aimyapi.generateCode(query, api._getHistory());
268
268
 
269
269
  api._addMessageToHistory({
270
270
  content: query,
@@ -273,13 +273,13 @@ import path from "path";
273
273
  });
274
274
 
275
275
  api._addMessageToHistory({
276
- content: '```\n' + code + '\n```',
276
+ content: '```\n' + codeResult.loggableCode + '\n```',
277
277
  role: "assistant",
278
278
  name: "assistant",
279
279
  });
280
280
 
281
281
  // run the code in the sandbox
282
- await aimyapi.runCode(code);
282
+ await aimyapi.runCode(codeResult.code);
283
283
  }
284
284
 
285
285
  await runQuery("How's the burger here?");
@@ -389,24 +389,20 @@ user: How are you today?
389
389
 
390
390
  assistant:
391
391
  \`\`\`
392
- import * as ApiDefs from './api.ts'
393
- (async() {
394
- try {
395
- api.print("I'm great, thanks for asking!");
396
- } catch(e) {
397
- console.error(e);
398
- }
399
- })();
392
+ api.print("I'm great, thanks for asking!");
400
393
  \`\`\`
394
+
401
395
  ```
402
396
 
403
397
  Aside from the code generation piece, documenting your API with clearly named functions and comments is important so that the LLM understands how it can be used. A big part of using AIMyAPI is testing out usecases and looking at the code that is generated. Problems can be solved by how you name your api, comments in the api, and examples.
404
398
 
405
399
  ## A note about history
406
400
 
407
- If you plan to use history, it is vital that you include the generated code in the history. Otherwise, the LLM will start to think that it doesn't need to generate code.
401
+ If you plan to use history, it is vital that you include the generated code in the history. Otherwise, the LLM will start to think that it doesn't need to generate code. Logging is also necessary for keeping track of Id's from past requests so that future requests can leverage that information.
402
+
403
+ See example2 for more an example on how to do this.
408
404
 
409
- In example2, note that responses to the user and relevant information is also added to the history so that the LLM can reference it for future queries.
405
+ TODO: Add more details explaining how this is done.
410
406
 
411
407
  ## Safety notes:
412
408
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  import { ChatCompletionRequestMessage } from "openai";
2
2
  import { QuickJSWASMModule } from "quickjs-emscripten";
3
3
  export declare function createBasePrompt(apiFilePath: string, documentationPath: string): string;
4
- export declare const generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug?: boolean) => Promise<string>;
4
+ export interface GenerateCodeResult {
5
+ code: string;
6
+ loggableCode: string;
7
+ rawResponse?: string;
8
+ }
9
+ export declare const generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug?: boolean) => Promise<GenerateCodeResult>;
5
10
  export interface AIMyAPIOptions {
6
11
  apiObject: object;
7
12
  apiExports: object;
@@ -12,16 +17,17 @@ export interface AIMyAPIOptions {
12
17
  apiDocsPath?: string;
13
18
  debug?: boolean;
14
19
  }
15
- export interface CreateWithAPIExports {
16
- generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[]) => Promise<string>;
20
+ export interface AIMyAPIInstance {
21
+ options: AIMyAPIOptions;
22
+ generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[]) => Promise<GenerateCodeResult>;
17
23
  runCode: (task: string) => Promise<void>;
18
- processRequest: (userQuery: string, context?: object) => Promise<string>;
24
+ processRequest: (userQuery: string, context?: object) => Promise<GenerateCodeResult>;
19
25
  }
20
- export interface AIMyAPIExports {
21
- createWithAPI: (options: AIMyAPIOptions) => Promise<CreateWithAPIExports>;
26
+ export interface AIMyAPIModuleExports {
27
+ createWithAPI: (options: AIMyAPIOptions) => Promise<AIMyAPIInstance>;
22
28
  createBasePrompt: (apiFilePath: string, documentationPath: string) => string;
23
- generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug: boolean) => Promise<string>;
29
+ generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug: boolean) => Promise<GenerateCodeResult>;
24
30
  createSandbox: (QuickJS: QuickJSWASMModule, globals: any) => Promise<any>;
25
31
  }
26
- declare const aimyapi: AIMyAPIExports;
32
+ declare const aimyapi: AIMyAPIModuleExports;
27
33
  export default aimyapi;
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ 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
- return;
35
+ return { code: '', loggableCode: '' };
36
36
  let generatedCode = '';
37
37
  const prompt = createTaskPrompt.replace("{{QUERY_TEXT}}", queryText);
38
38
  const messages = [
@@ -43,20 +43,11 @@ const generateCode = async function (queryText, userChatHistory, createTaskPromp
43
43
  ...userChatHistory,
44
44
  {
45
45
  role: "user",
46
- content: `${queryText}`,
46
+ content: `${queryText}.\nRespond only with code enclosed in \`\`\`.`,
47
47
  name: "user"
48
48
  }
49
49
  ];
50
- // TODO: I should switch this back to gpt3.5 turbo since it's cheaper
51
50
  try {
52
- // const task = await openai.createCompletion(
53
- // {
54
- // model: "text-davinci-003",
55
- // prompt,
56
- // temperature: 0.1,
57
- // max_tokens: 1100,
58
- // }
59
- // );
60
51
  const results = await openai.createChatCompletion({
61
52
  model: "gpt-3.5-turbo",
62
53
  messages: messages,
@@ -71,16 +62,18 @@ const generateCode = async function (queryText, userChatHistory, createTaskPromp
71
62
  // Return only the code between ``` and ``` (usually at the end of the completion)
72
63
  const codeStart = response.indexOf('```');
73
64
  const codeEnd = response.lastIndexOf('```');
74
- if (codeStart === -1 || codeEnd === -1 || codeStart === codeEnd)
75
- return '';
65
+ // error, no code detected inside the response
66
+ if (codeStart === -1 || codeEnd === -1 || codeStart === codeEnd) {
67
+ return { code: '', loggableCode: '', rawResponse: response };
68
+ }
76
69
  generatedCode = response.substring(codeStart + 3, codeEnd).replace('typescript', '');
77
- generatedCode = generatedCode.replace("./api.ts", apiPath);
78
- return generatedCode;
70
+ const codeHeader = `import * as ApiDefs from '${apiPath}'\n(async() {\n\ttry {`;
71
+ const codeFooter = `\n\t} catch(err) {\n\t\tconsole.error(err);\n\t}\n})();`;
72
+ return { code: codeHeader + generatedCode + codeFooter, loggableCode: generatedCode };
79
73
  }
80
74
  catch (err) {
81
75
  console.error(err);
82
- console.log("Prompt", messages);
83
- return '';
76
+ return { code: '', loggableCode: '' };
84
77
  }
85
78
  };
86
79
  exports.generateCode = generateCode;
@@ -101,9 +94,10 @@ async function createWithAPI(options) {
101
94
  const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug } = options;
102
95
  const createTaskPrompt = createBasePrompt(apiDefFilePath, apiDocsPath);
103
96
  return {
97
+ options,
104
98
  generateCode: async function (queryText, userChatHistory, currentContext = undefined) {
105
99
  if (!queryText)
106
- return '';
100
+ return { code: '', loggableCode: '' };
107
101
  return await (0, exports.generateCode)(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug);
108
102
  },
109
103
  runCode: async function (generatedCode) {
@@ -131,6 +125,9 @@ async function createWithAPI(options) {
131
125
  }
132
126
  }, options.debug);
133
127
  try {
128
+ if (debug) {
129
+ console.log("Running Code:\n", generatedCode);
130
+ }
134
131
  const res = await runTask(generatedCode);
135
132
  if (!res) {
136
133
  console.error("Task unsuccessful");
@@ -160,11 +157,8 @@ async function createWithAPI(options) {
160
157
  console.time("Generate Task");
161
158
  const generatedCode = await (0, exports.generateCode)(userQuery, [], createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath);
162
159
  console.timeEnd("Generate Task");
163
- if (debug) {
164
- console.log("Generated Code:", generatedCode);
165
- }
166
160
  console.time("Run Code");
167
- await this.runCode(generatedCode);
161
+ await this.runCode(generatedCode.code);
168
162
  console.timeEnd("Run Code");
169
163
  return generatedCode;
170
164
  }
@@ -14,17 +14,17 @@ import { API } from "./sales_api_impl";
14
14
  apiExports: APIExports,
15
15
  apiDefFilePath: path.join(__dirname, "./sales_api.ts"),
16
16
  apiDocsPath: path.join(__dirname, "./sales_api.md"),
17
- debug: false,
17
+ debug: true,
18
18
  })
19
19
 
20
- console.log("Print 'hello' three times.")
21
- await aimyapi.processRequest("Print 'hello' three times.");
20
+ // console.log("Print 'hello' three times.")
21
+ // await aimyapi.processRequest("Print 'hello' three times.");
22
22
 
23
- console.log("What month had the highest sales in 2020 for any business unit?")
24
- await aimyapi.processRequest("What was our best month in 2020");
23
+ // console.log("What month had the highest sales in 2020 for any business unit?")
24
+ // await aimyapi.processRequest("What was our best month in 2020");
25
25
 
26
- console.log("Which business unit had the highest sales in 2020?")
27
- await aimyapi.processRequest("Which business unit had the highest sales in 2020?");
26
+ // console.log("Which business unit had the highest sales in 2020?")
27
+ // await aimyapi.processRequest("Which business unit had the highest sales in 2020?");
28
28
 
29
29
  console.log("Compute the total sales for each month in 2020 then email the top 3 to test@email.com")
30
30
  await aimyapi.processRequest("Compute the total sales for each month in 2020 then email the top 3 to test@email.com");
@@ -1,7 +1,7 @@
1
- import AIMyAPI from "../lib";
2
- import { OrderingAPI } from "./ordering_api_impl";
3
- import * as APIExports from "./ordering_api";
4
1
  import path from "path";
2
+ import AIMyAPI, { GenerateCodeResult } from "../lib";
3
+ import * as APIExports from "./ordering_api";
4
+ import { OrderingAPI } from "./ordering_api_impl";
5
5
 
6
6
  // More complex fast food ordering example that uses chat history.
7
7
  // Fast food ordering example.
@@ -24,7 +24,7 @@ import path from "path";
24
24
  console.log(`Query: ${query}`)
25
25
 
26
26
  // generate the code for this query
27
- const code = await aimyapi.generateCode(query, api._getHistory());
27
+ const codeResult:GenerateCodeResult = await aimyapi.generateCode(query, api._getHistory());
28
28
 
29
29
  api._addMessageToHistory({
30
30
  content: query,
@@ -33,13 +33,13 @@ import path from "path";
33
33
  });
34
34
 
35
35
  api._addMessageToHistory({
36
- content: '```\n' + code.replace(options.apiDefFilePath, "./api.ts") + '\n```',
36
+ content: '```\n' + codeResult.loggableCode + '\n```',
37
37
  role: "assistant",
38
38
  name: "assistant",
39
39
  });
40
40
 
41
41
  // run the code in the sandbox
42
- await aimyapi.runCode(code);
42
+ await aimyapi.runCode(codeResult.code);
43
43
  }
44
44
 
45
45
  await runQuery("How's the burger here?");
@@ -10,109 +10,83 @@ user: How are you today?
10
10
 
11
11
  assistant:
12
12
  ```
13
- import * as ApiDefs from './api.ts'
14
- (async() {
15
- try {
16
- orderingApi.respondToUser("I'm great, thanks for asking!");
17
- } catch(e) {
18
- console.error(e);
19
- }
20
- })();
13
+ orderingApi.respondToUser("I'm great, thanks for asking!");
21
14
  ```
22
15
 
23
16
  user: Add a hamburger with no cheese to my order
24
17
 
25
18
  assistant:
26
19
  ```
27
- import * as ApiDefs from './api.ts'
28
- (async() {
29
- try {
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") );
37
- orderingApi.respondToUser("Ok, I added a Hamburger. What else would you like?");
38
- } catch(e) {
39
- console.error(e);
40
- }
41
- })();
20
+ const itemName = "Hamburger";
21
+ const item = ApiDefs.Menu.find((item) => item.name === itemName);
22
+ if (!item) {
23
+ throw new Error(`Item with name "${itemName}" not found`);
24
+ }
25
+
26
+ orderingApi.addItemToOrder(itemName, undefined, item.toppings.filter( topping => topping.name != "cheese") );
27
+ orderingApi.respondToUser("Ok, I added a Hamburger. What else would you like?");
42
28
  ```
43
29
 
44
- assistant: Added Hamburger with id 1
30
+ log: Added Hamburger with id 1
45
31
 
46
32
  user: I'd like a large pizza with mushrooms
47
33
 
48
34
  assistant:
49
35
  ```
50
- import * as ApiDefs from './api.ts'
51
- (async() {
52
- try {
53
- orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
54
- orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
55
- } catch(err) {
56
- orderingApi.respondToUser("Apologies, something went wrong with that request.");
57
- }
58
- })();
36
+ orderingApi.addItemToOrder("Pizza", ["Large"], ["mushrooms"]);
37
+ orderingApi.respondToUser("Ok, I added a Large Pizza with mushrooms");
59
38
  ```
60
39
 
61
40
  user: Add a hamburger with bacon
62
41
 
63
42
  assistant:
64
43
  ```
65
- import * as ApiDefs from './api.ts'
66
- (async() {
67
- try {
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?");
76
- } catch(e) {
77
- console.error(e);
78
- }
79
- })();
44
+ const itemName = "Hamburger";
45
+ const item = ApiDefs.Menu.find((item) => item.name === itemName);
46
+ if (!item) {
47
+ throw new Error(`Item with name "${itemName}" not found`);
48
+ }
49
+
50
+ orderingApi.addItemToOrder(itemName, undefined, [...item.toppings, "bacon"]);
51
+ orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
80
52
  ```
81
53
 
82
- assistant: Added Hamburger with id 2
54
+ log: Added Hamburger with id 2
83
55
 
84
56
  user: Add jalapenos to that
85
57
 
86
58
  assistant:
87
59
  ```
88
- import * as ApiDefs from './api.ts'
89
- (async() {
90
- try {
91
- const existingItem = orderingApi.getItemInOrder("2");
92
-
93
- if(existingItem) {
94
- orderingApi.modifyItemInOrder("2", existingItem.customizations.map(item => item.name), [...existingItem.toppings, "jalapenos"]);
95
- orderingApi.respondToUser("Ok, I added jalapenos to your Hamburger");
96
- } else {
97
- orderingApi.respondToUser("Hmm, I can't find that item.");
98
- }
99
- } catch(e) {
100
- orderingApi.respondToUser("Apologies, something went wrong with that request.");
101
- console.error(e);
102
- }
103
- })();
60
+ const existingItem = orderingApi.getItemInOrder("2");
61
+
62
+ if(existingItem) {
63
+ orderingApi.modifyItemInOrder("2", existingItem.customizations.map(item => item.name), [...existingItem.toppings, "jalapenos"]);
64
+ orderingApi.respondToUser("Ok, I added jalapenos to your Hamburger");
65
+ } else {
66
+ orderingApi.respondToUser("Hmm, I can't find that item.");
67
+ }
104
68
  ```
105
69
 
70
+ user: Add a hamburger with no lettuce
71
+
72
+ assistant:
73
+ ```
74
+ const itemName = "Hamburger";
75
+ const item = ApiDefs.Menu.find((item) => item.name === itemName);
76
+ if (!item) {
77
+ throw new Error(`Item with name "${itemName}" not found`);
78
+ }
79
+
80
+ orderingApi.addItemToOrder(itemName, undefined, [...item.toppings.filter(topping => topping != "lettuce")]);
81
+ orderingApi.respondToUser("Ok, I added a Hamburger with no cheese or onions. What else would you like?");
82
+ ```
83
+
84
+ log: Added Hamburger with id 2
85
+
86
+
106
87
  user: I want an elephant.
107
88
 
108
89
  assistant:
109
90
  ```
110
- import * as ApiDefs from './api.ts'
111
- (async() {
112
- try {
113
- orderingApi.respondToUser("I'm sorry, but that isn't on our menu.");
114
- } catch(e) {
115
- console.error(e);
116
- }
117
- })();
91
+ orderingApi.respondToUser("I'm sorry, but that isn't on our menu.");
118
92
  ```
@@ -87,12 +87,13 @@ export class OrderingAPI implements OrderingAPIInterface {
87
87
 
88
88
  this._history.push({
89
89
  role: "user",
90
- content: `I see you have added added ${itemName} with id ${newItem.orderId}`,
90
+ name: "log",
91
+ content: `added added ${itemName} with id ${newItem.orderId}`,
91
92
  });
92
93
  this.displayItem(newItem, true);
93
94
  }
94
95
 
95
- getItemInOrder(itemOrderId: string): MenuItemBase {
96
+ getItemInOrder(itemOrderId: string): MenuItemBase | undefined {
96
97
  const item = this._order.find((item) => item.orderId === itemOrderId);
97
98
  if (!item) {
98
99
  return undefined;
@@ -106,7 +107,8 @@ export class OrderingAPI implements OrderingAPIInterface {
106
107
 
107
108
  this._history.push({
108
109
  role: "user",
109
- content: `I see you have removed item ${itemOrderId}`,
110
+ name: "log",
111
+ content: `removed item ${itemOrderId}`,
110
112
  });
111
113
  this.respondToUser(`Removed item ${itemOrderId}`);
112
114
  }
@@ -140,7 +142,8 @@ export class OrderingAPI implements OrderingAPIInterface {
140
142
 
141
143
  this._history.push({
142
144
  role: "user",
143
- content: `I see you have modified item ${itemOrderId}`,
145
+ name: "log",
146
+ content: `modified item ${itemOrderId}`,
144
147
  });
145
148
  this.respondToUser(`Modified item ${itemOrderId}`);
146
149
  }
@@ -188,7 +191,7 @@ export class OrderingAPI implements OrderingAPIInterface {
188
191
  displayOrder() {
189
192
  this.respondToUser("----\n\nDisplaying order:\n\n");
190
193
  this._order.forEach((item) => this.displayItem(item));
191
- this.respondToUser(`--\tTotal:\t\t$${this.getOrderTotal()}`);
194
+ this.respondToUser(`--\tTotal:\t\t$${this.getOrderTotal().toFixed(2)}`);
192
195
  }
193
196
 
194
197
  _addMessageToHistory(message: ChatCompletionRequestMessage) {
@@ -4,12 +4,5 @@ user: How are you today?
4
4
 
5
5
  assistant:
6
6
  ```
7
- import * as ApiDefs from './api.ts'
8
- (async() {
9
- try {
10
- api.print("I'm great, thanks for asking!");
11
- } catch(e) {
12
- console.error(e);
13
- }
14
- })();
7
+ api.print("I'm great, thanks for asking!");
15
8
  ```
package/lib/index.ts CHANGED
@@ -31,10 +31,16 @@ export function createBasePrompt(apiFilePath:string, documentationPath: string):
31
31
  return createTaskPrompt;
32
32
  }
33
33
 
34
+ export interface GenerateCodeResult {
35
+ code: string;
36
+ loggableCode: string;
37
+ rawResponse?: string;
38
+ }
39
+
34
40
  // FIXME: add an options parameter and allow specifying the token limit
35
- export const generateCode = async function(queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean = false): Promise<string> {
41
+ export const generateCode = async function(queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean = false): Promise<GenerateCodeResult> {
36
42
  if(!queryText)
37
- return;
43
+ return { code: '', loggableCode: '' };
38
44
 
39
45
  let generatedCode = '';
40
46
  const prompt = createTaskPrompt.replace("{{QUERY_TEXT}}", queryText);
@@ -46,21 +52,11 @@ export const generateCode = async function(queryText:string, userChatHistory:Cha
46
52
  ...userChatHistory,
47
53
  {
48
54
  role: "user",
49
- content: `${queryText}`,
55
+ content: `${queryText}.\nRespond only with code enclosed in \`\`\`.`,
50
56
  name: "user"
51
57
  }
52
58
  ];
53
- // TODO: I should switch this back to gpt3.5 turbo since it's cheaper
54
59
  try {
55
- // const task = await openai.createCompletion(
56
- // {
57
- // model: "text-davinci-003",
58
- // prompt,
59
- // temperature: 0.1,
60
- // max_tokens: 1100,
61
- // }
62
- // );
63
-
64
60
  const results = await openai.createChatCompletion({
65
61
  model: "gpt-3.5-turbo",
66
62
  messages: messages,
@@ -81,17 +77,19 @@ export const generateCode = async function(queryText:string, userChatHistory:Cha
81
77
  const codeStart = response.indexOf('```');
82
78
  const codeEnd = response.lastIndexOf('```');
83
79
 
84
- if(codeStart === -1 || codeEnd === -1 || codeStart === codeEnd)
85
- return '';
80
+ // error, no code detected inside the response
81
+ if(codeStart === -1 || codeEnd === -1 || codeStart === codeEnd) {
82
+ return { code: '', loggableCode: '', rawResponse: response };
83
+ }
86
84
 
87
85
  generatedCode = response.substring(codeStart + 3, codeEnd).replace('typescript', '');
88
86
 
89
- generatedCode = generatedCode.replace("./api.ts", apiPath);
90
- return generatedCode;
87
+ const codeHeader = `import * as ApiDefs from '${apiPath}'\n(async() {\n\ttry {`;
88
+ const codeFooter = `\n\t} catch(err) {\n\t\tconsole.error(err);\n\t}\n})();`;
89
+ return { code: codeHeader + generatedCode + codeFooter, loggableCode: generatedCode };
91
90
  } catch(err) {
92
91
  console.error(err);
93
- console.log("Prompt", messages);
94
- return '';
92
+ return { code: '', loggableCode: '' };
95
93
  }
96
94
  };
97
95
 
@@ -108,16 +106,17 @@ export interface AIMyAPIOptions {
108
106
  debug?: boolean;
109
107
  };
110
108
 
111
- export interface CreateWithAPIExports {
109
+ export interface AIMyAPIInstance {
112
110
  // see xample 2
113
- generateCode: (queryText:string, userChatHistory:ChatCompletionRequestMessage[]) => Promise<string>;
111
+ options:AIMyAPIOptions;
112
+ generateCode: (queryText:string, userChatHistory:ChatCompletionRequestMessage[]) => Promise<GenerateCodeResult>;
114
113
  runCode: (task:string) => Promise<void>;
115
114
  // run a single request with no history
116
- processRequest: (userQuery:string, context?: object) => Promise<string>;
115
+ processRequest: (userQuery:string, context?: object) => Promise<GenerateCodeResult>;
117
116
 
118
117
  }
119
118
 
120
- async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExports> {
119
+ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
121
120
  // extend options with defaults
122
121
  options = {
123
122
  apiGlobalName: "api",
@@ -136,9 +135,10 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExpor
136
135
  const createTaskPrompt = createBasePrompt( apiDefFilePath, apiDocsPath);
137
136
 
138
137
  return {
138
+ options,
139
139
  generateCode: async function(queryText:string, userChatHistory:ChatCompletionRequestMessage[], currentContext:any = undefined) {
140
140
  if(!queryText)
141
- return '';
141
+ return { code: '', loggableCode: '' };
142
142
 
143
143
  return await generateCode(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug);
144
144
  },
@@ -171,6 +171,10 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExpor
171
171
  }, options.debug);
172
172
 
173
173
  try {
174
+ if(debug) {
175
+ console.log("Running Code:\n", generatedCode);
176
+ }
177
+
174
178
  const res = await runTask(generatedCode);
175
179
 
176
180
  if(!res) {
@@ -196,7 +200,7 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExpor
196
200
  vm.dispose()
197
201
 
198
202
  },
199
- processRequest: async function (userQuery, currentContext:any = undefined):Promise<string> {
203
+ processRequest: async function (userQuery, currentContext:any = undefined):Promise<GenerateCodeResult> {
200
204
  // Create prompt
201
205
 
202
206
  if(debug) {
@@ -205,15 +209,11 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExpor
205
209
 
206
210
  // Generate Code
207
211
  console.time("Generate Task")
208
- const generatedCode = await generateCode(userQuery, [], createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : "" ), apiDefFilePath);
212
+ const generatedCode:GenerateCodeResult = await generateCode(userQuery, [], createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : "" ), apiDefFilePath);
209
213
  console.timeEnd("Generate Task")
210
214
 
211
- if(debug) {
212
- console.log("Generated Code:", generatedCode);
213
- }
214
-
215
215
  console.time("Run Code")
216
- await this.runCode(generatedCode);
216
+ await this.runCode(generatedCode.code);
217
217
  console.timeEnd("Run Code")
218
218
 
219
219
  return generatedCode;
@@ -222,15 +222,15 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<CreateWithAPIExpor
222
222
 
223
223
  }
224
224
 
225
- export interface AIMyAPIExports {
226
- createWithAPI: (options:AIMyAPIOptions) => Promise<CreateWithAPIExports>;
225
+ export interface AIMyAPIModuleExports {
226
+ createWithAPI: (options:AIMyAPIOptions) => Promise<AIMyAPIInstance>;
227
227
 
228
228
  createBasePrompt: (apiFilePath:string, documentationPath: string) => string;
229
- generateCode: (queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean) => Promise<string>;
229
+ generateCode: (queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean) => Promise<GenerateCodeResult>;
230
230
  createSandbox: (QuickJS:QuickJSWASMModule, globals: any) => Promise<any>;
231
231
  }
232
232
 
233
- const aimyapi:AIMyAPIExports = {
233
+ const aimyapi:AIMyAPIModuleExports = {
234
234
  // Standard way of using the library
235
235
  createWithAPI,
236
236
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aimyapi",
3
- "version": "0.1.9",
4
- "description": "AI My API! Use LLMs to create small programs that safely* run and make calls against your API.",
3
+ "version": "0.1.11",
4
+ "description": "AI My API! Use LLMs to create small programs that safely* run and make calls against your API. Similar to ChatGPT's Code Interpreter.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "directories": {
@@ -1,5 +1,5 @@
1
1
  You are a helpful assistant who speaks only in Typescript.
2
- You fulfill user requests by writing code.
2
+ You work just like a regular assistant, but you fulfill user requests by writing code.
3
3
  You comment your code and are sure to properly escape your strings and follow good programming practices.
4
4
 
5
5
  Here is the API that you will use:
@@ -11,6 +11,8 @@ Here is the API that you will use:
11
11
 
12
12
  Documentation:
13
13
 
14
+ Note: the api definitions are available as `ApiDefs`;
15
+
14
16
  {{DOCUMENTATION}}
15
17
 
16
18
  Current Context: