-
Notifications
You must be signed in to change notification settings - Fork 0
/
apiassistant.js
118 lines (94 loc) · 3.63 KB
/
apiassistant.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import OpenAI from 'openai';
import utils from './common/utils.js';
const openai = new OpenAI(process.env.OPENAI_API_KEY);
class APIAssistant {
constructor(functionsJson, actionProvider, safetyContext, fromId = null) {
const functions = functionsJson.map((f) => {
return {
"type": "function",
"function": f
};
});
this.actionProvider = actionProvider;
if (fromId === null) {
this.assistant = openai.beta.assistants.create({
instructions: `You are an API gateway. Use the provided functions to answer questions. Use the following context as guidelines for your responses:${safetyContext}}`,
model: "gpt-4-1106-preview",
tools: functions,
});
} else {
this.assistant = openai.beta.assistants.retrieve(fromId);
}
}
async fulfillAction(requiredAction) {
if (requiredAction.type !== "submit_tool_outputs") {
throw new Error("Unsupported action type: " + requiredAction.type);
}
return requiredAction.submit_tool_outputs.tool_calls.map((tool_call) => {
if (tool_call.type !== "function") {
throw new Error("Unsupported tool type: " + tool_call.type);
}
const toolName = utils.snakeToCamel(tool_call.function.name);
const toolArgs = tool_call.function.arguments;
if (!utils.hasMethod(this.actionProvider, toolName)) {
throw new Error("Unsupported tool: " + toolName);
}
const tool = this.actionProvider[toolName];
const args = JSON.parse(toolArgs);
return {
tool_call_id: tool_call.id,
output: JSON.stringify(tool(...Object.values(args)))
};
});
}
async getAnswer(question) {
// Create a thread
const thread = await openai.beta.threads.create();
// Add a message to the thread
await openai.beta.threads.messages.create(
thread.id,
{
role: "user",
content: question
}
);
this.assistant = await this.assistant
// Run the thread against the assistant
var run = await openai.beta.threads.runs.create(
thread.id,
{
assistant_id: this.assistant.id,
// instructions: "Please address the user as Jane Doe. The user has a premium account."
}
);
while (run.status !== "completed") {
run = await openai.beta.threads.runs.retrieve(
thread.id,
run.id
)
if (run.status === "in_progress" || run.status === "queued") {
await new Promise(resolve => setTimeout(resolve, 1000));
continue
}
if (run.status === "requires_action") {
const toolOutputs = await this.fulfillAction(run.required_action)
await openai.beta.threads.runs.submitToolOutputs(
thread.id,
run.id,
{
tool_outputs: toolOutputs
}
);
continue;
}
if (run.status !== "completed") {
throw new Error(`Unexpected run status: ${run.status}: ${JSON.stringify(run)}`);
}
}
const messages = await openai.beta.threads.messages.list(
thread.id
);
return messages.data[0].content[0].text.value
}
}
export default APIAssistant;