aimyapi 0.1.10 → 0.1.13
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 +16 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +9 -9
- package/lib/index.ts +12 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# AI My API
|
|
2
2
|
|
|
3
|
-
Build AI assistants that use your API's and respond to natural language queries by writing small programs that are executed in a [QuickJS](https://github.com/justjake/quickjs-emscripten) sandbox.
|
|
4
|
-
|
|
5
|
-
for example, being able to sort or filter your data in new ways, email or text yourself results, or combine the results of different operations and API's.
|
|
3
|
+
Build AI assistants that use your API's and respond to natural language queries by writing small programs that are executed in a [QuickJS](https://github.com/justjake/quickjs-emscripten) sandbox. Similar to chatGPT Code Interpreter but running on your servers and calling your own API.
|
|
4
|
+
|
|
5
|
+
AIMyAPI writes the glue between your various API functions unlocking new functionality without having to write any code. With the right building blocks, AIMyAPI can even invent new functionality you didn't originally plan for - for example, being able to sort or filter your data in new ways, email or text yourself results, or combine the results of different operations and API's.
|
|
6
6
|
|
|
7
7
|
Uses the OpenAI API and requires an API key.
|
|
8
8
|
|
|
@@ -45,7 +45,7 @@ declare global {
|
|
|
45
45
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Implement it:
|
|
48
|
+
Implement it (`sales_api_impl.ts`):
|
|
49
49
|
```
|
|
50
50
|
export class API implements APIInterface {
|
|
51
51
|
|
|
@@ -53,6 +53,18 @@ export class API implements APIInterface {
|
|
|
53
53
|
...
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Document it (`sales_api.md`):
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Examples of how you should respond:
|
|
60
|
+
|
|
61
|
+
user: How are you today?
|
|
62
|
+
|
|
63
|
+
assistant:
|
|
64
|
+
|
|
65
|
+
api.print("I'm great, thanks for asking!");
|
|
66
|
+
```
|
|
67
|
+
|
|
56
68
|
Instantiate your api and AIMyAPI. AIMyAPI will wrap your API so that it can be called from within the QuickJS sandbox.
|
|
57
69
|
|
|
58
70
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ export declare function createBasePrompt(apiFilePath: string, documentationPath:
|
|
|
4
4
|
export interface GenerateCodeResult {
|
|
5
5
|
code: string;
|
|
6
6
|
loggableCode: string;
|
|
7
|
+
rawResponse?: string;
|
|
7
8
|
}
|
|
8
|
-
export declare const generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug?: boolean) => Promise<GenerateCodeResult>;
|
|
9
|
+
export declare const generateCode: (queryText: string, userChatHistory: ChatCompletionRequestMessage[], createTaskPrompt: string, apiPath: string, debug?: boolean, model?: string) => Promise<GenerateCodeResult>;
|
|
9
10
|
export interface AIMyAPIOptions {
|
|
10
11
|
apiObject: object;
|
|
11
12
|
apiExports: object;
|
|
@@ -15,6 +16,7 @@ export interface AIMyAPIOptions {
|
|
|
15
16
|
apiGlobalName?: string;
|
|
16
17
|
apiDocsPath?: string;
|
|
17
18
|
debug?: boolean;
|
|
19
|
+
model?: string;
|
|
18
20
|
}
|
|
19
21
|
export interface AIMyAPIInstance {
|
|
20
22
|
options: AIMyAPIOptions;
|
package/dist/index.js
CHANGED
|
@@ -30,9 +30,9 @@ function createBasePrompt(apiFilePath, documentationPath) {
|
|
|
30
30
|
}
|
|
31
31
|
exports.createBasePrompt = createBasePrompt;
|
|
32
32
|
// FIXME: add an options parameter and allow specifying the token limit
|
|
33
|
-
const generateCode = async function (queryText, userChatHistory, createTaskPrompt, apiPath, debug = false) {
|
|
33
|
+
const generateCode = async function (queryText, userChatHistory, createTaskPrompt, apiPath, debug = false, model = "gpt-4o") {
|
|
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,13 +43,13 @@ 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
50
|
try {
|
|
51
51
|
const results = await openai.createChatCompletion({
|
|
52
|
-
model
|
|
52
|
+
model,
|
|
53
53
|
messages: messages,
|
|
54
54
|
temperature: 0.1,
|
|
55
55
|
max_tokens: 700,
|
|
@@ -64,16 +64,15 @@ const generateCode = async function (queryText, userChatHistory, createTaskPromp
|
|
|
64
64
|
const codeEnd = response.lastIndexOf('```');
|
|
65
65
|
// error, no code detected inside the response
|
|
66
66
|
if (codeStart === -1 || codeEnd === -1 || codeStart === codeEnd) {
|
|
67
|
-
return { code: '', loggableCode: '' };
|
|
67
|
+
return { code: '', loggableCode: '', rawResponse: response };
|
|
68
68
|
}
|
|
69
69
|
generatedCode = response.substring(codeStart + 3, codeEnd).replace('typescript', '');
|
|
70
|
-
const codeHeader =
|
|
70
|
+
const codeHeader = `import * as ApiDefs from '${apiPath}'\n(async() {\n\ttry {`;
|
|
71
71
|
const codeFooter = `\n\t} catch(err) {\n\t\tconsole.error(err);\n\t}\n})();`;
|
|
72
72
|
return { code: codeHeader + generatedCode + codeFooter, loggableCode: generatedCode };
|
|
73
73
|
}
|
|
74
74
|
catch (err) {
|
|
75
75
|
console.error(err);
|
|
76
|
-
console.log("Prompt", messages);
|
|
77
76
|
return { code: '', loggableCode: '' };
|
|
78
77
|
}
|
|
79
78
|
};
|
|
@@ -87,19 +86,20 @@ async function createWithAPI(options) {
|
|
|
87
86
|
apiGlobals: {},
|
|
88
87
|
apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
|
|
89
88
|
debug: false,
|
|
89
|
+
model: "gpt-4o",
|
|
90
90
|
...options
|
|
91
91
|
};
|
|
92
92
|
if (!options.apiObject || !options.apiDefFilePath) {
|
|
93
93
|
throw new Error("apiObject and apiFilePath are required");
|
|
94
94
|
}
|
|
95
|
-
const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug } = options;
|
|
95
|
+
const { apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model } = options;
|
|
96
96
|
const createTaskPrompt = createBasePrompt(apiDefFilePath, apiDocsPath);
|
|
97
97
|
return {
|
|
98
98
|
options,
|
|
99
99
|
generateCode: async function (queryText, userChatHistory, currentContext = undefined) {
|
|
100
100
|
if (!queryText)
|
|
101
101
|
return { code: '', loggableCode: '' };
|
|
102
|
-
return await (0, exports.generateCode)(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug);
|
|
102
|
+
return await (0, exports.generateCode)(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug, model);
|
|
103
103
|
},
|
|
104
104
|
runCode: async function (generatedCode) {
|
|
105
105
|
if (!QuickJS) {
|
package/lib/index.ts
CHANGED
|
@@ -34,12 +34,13 @@ export function createBasePrompt(apiFilePath:string, documentationPath: string):
|
|
|
34
34
|
export interface GenerateCodeResult {
|
|
35
35
|
code: string;
|
|
36
36
|
loggableCode: string;
|
|
37
|
+
rawResponse?: string;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
// FIXME: add an options parameter and allow specifying the token limit
|
|
40
|
-
export const generateCode = async function(queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean = false): Promise<GenerateCodeResult> {
|
|
41
|
+
export const generateCode = async function(queryText:string, userChatHistory:ChatCompletionRequestMessage[], createTaskPrompt:string, apiPath:string, debug:boolean = false, model="gpt-4o"): Promise<GenerateCodeResult> {
|
|
41
42
|
if(!queryText)
|
|
42
|
-
return;
|
|
43
|
+
return { code: '', loggableCode: '' };
|
|
43
44
|
|
|
44
45
|
let generatedCode = '';
|
|
45
46
|
const prompt = createTaskPrompt.replace("{{QUERY_TEXT}}", queryText);
|
|
@@ -51,13 +52,13 @@ export const generateCode = async function(queryText:string, userChatHistory:Cha
|
|
|
51
52
|
...userChatHistory,
|
|
52
53
|
{
|
|
53
54
|
role: "user",
|
|
54
|
-
content: `${queryText}
|
|
55
|
+
content: `${queryText}.\nRespond only with code enclosed in \`\`\`.`,
|
|
55
56
|
name: "user"
|
|
56
57
|
}
|
|
57
58
|
];
|
|
58
59
|
try {
|
|
59
60
|
const results = await openai.createChatCompletion({
|
|
60
|
-
model
|
|
61
|
+
model,
|
|
61
62
|
messages: messages,
|
|
62
63
|
temperature: 0.1,
|
|
63
64
|
max_tokens: 700,
|
|
@@ -78,17 +79,16 @@ export const generateCode = async function(queryText:string, userChatHistory:Cha
|
|
|
78
79
|
|
|
79
80
|
// error, no code detected inside the response
|
|
80
81
|
if(codeStart === -1 || codeEnd === -1 || codeStart === codeEnd) {
|
|
81
|
-
return { code: '', loggableCode: '' };
|
|
82
|
+
return { code: '', loggableCode: '', rawResponse: response };
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
generatedCode = response.substring(codeStart + 3, codeEnd).replace('typescript', '');
|
|
85
86
|
|
|
86
|
-
const codeHeader =
|
|
87
|
+
const codeHeader = `import * as ApiDefs from '${apiPath}'\n(async() {\n\ttry {`;
|
|
87
88
|
const codeFooter = `\n\t} catch(err) {\n\t\tconsole.error(err);\n\t}\n})();`;
|
|
88
89
|
return { code: codeHeader + generatedCode + codeFooter, loggableCode: generatedCode };
|
|
89
90
|
} catch(err) {
|
|
90
91
|
console.error(err);
|
|
91
|
-
console.log("Prompt", messages);
|
|
92
92
|
return { code: '', loggableCode: '' };
|
|
93
93
|
}
|
|
94
94
|
};
|
|
@@ -104,6 +104,7 @@ export interface AIMyAPIOptions {
|
|
|
104
104
|
apiGlobalName?: string;
|
|
105
105
|
apiDocsPath?: string;
|
|
106
106
|
debug?: boolean;
|
|
107
|
+
model?: string;
|
|
107
108
|
};
|
|
108
109
|
|
|
109
110
|
export interface AIMyAPIInstance {
|
|
@@ -122,7 +123,8 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
122
123
|
apiGlobalName: "api",
|
|
123
124
|
apiGlobals: {},
|
|
124
125
|
apiWhitelist: Object.getOwnPropertyNames(Object.getPrototypeOf(options.apiObject)).filter((f) => f !== "constructor" && !f.startsWith("_")),
|
|
125
|
-
debug: false,
|
|
126
|
+
debug: false,
|
|
127
|
+
model: "gpt-4o",
|
|
126
128
|
...options
|
|
127
129
|
} as AIMyAPIOptions;
|
|
128
130
|
|
|
@@ -130,7 +132,7 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
130
132
|
throw new Error("apiObject and apiFilePath are required");
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
const {apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug} = options;
|
|
135
|
+
const {apiObject, apiWhitelist, apiGlobalName, apiExports, apiDefFilePath, apiDocsPath, debug, model} = options;
|
|
134
136
|
|
|
135
137
|
const createTaskPrompt = createBasePrompt( apiDefFilePath, apiDocsPath);
|
|
136
138
|
|
|
@@ -140,7 +142,7 @@ async function createWithAPI(options:AIMyAPIOptions): Promise<AIMyAPIInstance> {
|
|
|
140
142
|
if(!queryText)
|
|
141
143
|
return { code: '', loggableCode: '' };
|
|
142
144
|
|
|
143
|
-
return await generateCode(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug);
|
|
145
|
+
return await generateCode(queryText, userChatHistory, createTaskPrompt.replace("{{CONTEXT}}", currentContext ? "```" + JSON.stringify(currentContext, null, 2) + "```" : ""), apiDefFilePath, debug, model);
|
|
144
146
|
},
|
|
145
147
|
runCode: async function(generatedCode:string) {
|
|
146
148
|
if(!QuickJS) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aimyapi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
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",
|