@proteinjs/conversation 1.7.4 → 2.0.0
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/CHANGELOG.md +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/src/CodegenConversation.d.ts.map +1 -1
- package/dist/src/CodegenConversation.js +9 -6
- package/dist/src/CodegenConversation.js.map +1 -1
- package/dist/src/Conversation.d.ts +30 -6
- package/dist/src/Conversation.d.ts.map +1 -1
- package/dist/src/Conversation.js +119 -47
- package/dist/src/Conversation.js.map +1 -1
- package/dist/src/OpenAi.d.ts +57 -15
- package/dist/src/OpenAi.d.ts.map +1 -1
- package/dist/src/OpenAi.js +148 -124
- package/dist/src/OpenAi.js.map +1 -1
- package/dist/src/OpenAiStreamProcessor.d.ts +5 -1
- package/dist/src/OpenAiStreamProcessor.d.ts.map +1 -1
- package/dist/src/OpenAiStreamProcessor.js +25 -5
- package/dist/src/OpenAiStreamProcessor.js.map +1 -1
- package/dist/src/UsageData.d.ts +38 -0
- package/dist/src/UsageData.d.ts.map +1 -0
- package/dist/src/UsageData.js +47 -0
- package/dist/src/UsageData.js.map +1 -0
- package/dist/src/code_template/Code.js +1 -1
- package/dist/src/code_template/Code.js.map +1 -1
- package/dist/test/openai/openai.generateList.test.js +1 -1
- package/dist/test/openai/openai.generateList.test.js.map +1 -1
- package/index.ts +1 -0
- package/package.json +5 -5
- package/src/CodegenConversation.ts +6 -3
- package/src/Conversation.ts +87 -80
- package/src/OpenAi.ts +197 -210
- package/src/OpenAiStreamProcessor.ts +25 -6
- package/src/UsageData.ts +76 -0
- package/src/code_template/Code.ts +1 -1
- package/test/openai/openai.generateList.test.ts +3 -3
package/src/OpenAi.ts
CHANGED
|
@@ -15,75 +15,95 @@ import { ChatCompletionMessageParamFactory } from './ChatCompletionMessageParamF
|
|
|
15
15
|
import { Stream } from 'openai/streaming';
|
|
16
16
|
import { Readable } from 'stream';
|
|
17
17
|
import { OpenAiStreamProcessor } from './OpenAiStreamProcessor';
|
|
18
|
+
import { UsageData, UsageDataAccumulator } from './UsageData';
|
|
18
19
|
|
|
19
20
|
function delay(ms: number) {
|
|
20
21
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
export type GenerateResponseParams = {
|
|
25
|
+
messages: (string | ChatCompletionMessageParam)[];
|
|
26
|
+
model?: TiktokenModel;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type GenerateResponseReturn = {
|
|
30
|
+
message: string;
|
|
31
|
+
usagedata: UsageData;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type GenerateStreamingResponseParams = GenerateResponseParams & {
|
|
35
|
+
abortSignal?: AbortSignal;
|
|
36
|
+
onUsageData?: (usageData: UsageData) => Promise<void>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type GenerateResponseHelperParams = GenerateStreamingResponseParams & {
|
|
40
|
+
model: TiktokenModel;
|
|
41
|
+
stream: boolean;
|
|
42
|
+
currentFunctionCalls?: number;
|
|
43
|
+
usageDataAccumulator?: UsageDataAccumulator;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type OpenAiParams = {
|
|
47
|
+
model?: TiktokenModel;
|
|
48
|
+
history?: MessageHistory;
|
|
49
|
+
functions?: Omit<Function, 'instructions'>[];
|
|
50
|
+
messageModerators?: MessageModerator[];
|
|
51
|
+
maxFunctionCalls?: number;
|
|
52
|
+
logLevel?: LogLevel;
|
|
53
|
+
};
|
|
54
|
+
|
|
23
55
|
export const DEFAULT_MODEL: TiktokenModel = 'gpt-3.5-turbo';
|
|
56
|
+
export const DEFAULT_MAX_FUNCTION_CALLS = 50;
|
|
57
|
+
|
|
24
58
|
export class OpenAi {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
private model: TiktokenModel;
|
|
60
|
+
private history: MessageHistory;
|
|
61
|
+
private functions?: Omit<Function, 'instructions'>[];
|
|
62
|
+
private messageModerators?: MessageModerator[];
|
|
63
|
+
private maxFunctionCalls: number;
|
|
64
|
+
private logLevel?: LogLevel;
|
|
65
|
+
|
|
66
|
+
constructor({
|
|
67
|
+
model = DEFAULT_MODEL,
|
|
68
|
+
history = new MessageHistory(),
|
|
69
|
+
functions,
|
|
70
|
+
messageModerators,
|
|
71
|
+
maxFunctionCalls = DEFAULT_MAX_FUNCTION_CALLS,
|
|
72
|
+
logLevel,
|
|
73
|
+
}: OpenAiParams = {}) {
|
|
74
|
+
this.model = model;
|
|
75
|
+
this.history = history;
|
|
76
|
+
this.functions = functions;
|
|
77
|
+
this.messageModerators = messageModerators;
|
|
78
|
+
this.maxFunctionCalls = maxFunctionCalls;
|
|
79
|
+
this.logLevel = logLevel;
|
|
46
80
|
}
|
|
47
81
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
abortSignal?: AbortSignal,
|
|
55
|
-
logLevel: LogLevel = 'info',
|
|
56
|
-
maxFunctionCalls: number = 50
|
|
57
|
-
): Promise<Readable> {
|
|
58
|
-
return (await this.generateResponseHelper(
|
|
59
|
-
messages,
|
|
60
|
-
true,
|
|
61
|
-
0,
|
|
62
|
-
model,
|
|
63
|
-
history,
|
|
64
|
-
functions,
|
|
65
|
-
messageModerators,
|
|
66
|
-
abortSignal,
|
|
67
|
-
logLevel,
|
|
68
|
-
maxFunctionCalls
|
|
69
|
-
)) as Readable;
|
|
82
|
+
async generateResponse({ model, ...rest }: GenerateResponseParams): Promise<GenerateResponseReturn> {
|
|
83
|
+
return (await this.generateResponseHelper({
|
|
84
|
+
model: model ?? this.model,
|
|
85
|
+
stream: false,
|
|
86
|
+
...rest,
|
|
87
|
+
})) as GenerateResponseReturn;
|
|
70
88
|
}
|
|
71
89
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
abortSignal
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
90
|
+
async generateStreamingResponse({ model, ...rest }: GenerateStreamingResponseParams): Promise<Readable> {
|
|
91
|
+
return (await this.generateResponseHelper({ model: model ?? this.model, stream: true, ...rest })) as Readable;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private async generateResponseHelper({
|
|
95
|
+
messages,
|
|
96
|
+
model,
|
|
97
|
+
stream,
|
|
98
|
+
abortSignal,
|
|
99
|
+
onUsageData,
|
|
100
|
+
usageDataAccumulator,
|
|
101
|
+
currentFunctionCalls = 0,
|
|
102
|
+
}: GenerateResponseHelperParams): Promise<GenerateResponseReturn | Readable> {
|
|
103
|
+
const logger = new Logger({ name: 'OpenAi.generateResponseHelper', logLevel: this.logLevel });
|
|
104
|
+
this.updateMessageHistory(messages);
|
|
105
|
+
const resolvedUsageDataAccumulator = usageDataAccumulator ?? new UsageDataAccumulator({ model });
|
|
106
|
+
const response = await this.executeRequest(model, stream, resolvedUsageDataAccumulator, abortSignal);
|
|
87
107
|
if (stream) {
|
|
88
108
|
logger.info({ message: `Processing response stream` });
|
|
89
109
|
const inputStream = response as Stream<ChatCompletionChunk>;
|
|
@@ -95,35 +115,36 @@ export class OpenAi {
|
|
|
95
115
|
|
|
96
116
|
// For the initial call to `generateResponseHelper`, return the `OpenAiStreamProcessor` output stream
|
|
97
117
|
const onToolCalls = ((toolCalls, currentFunctionCalls) =>
|
|
98
|
-
|
|
118
|
+
this.handleToolCalls(
|
|
99
119
|
toolCalls,
|
|
100
|
-
true,
|
|
101
|
-
currentFunctionCalls,
|
|
102
|
-
updatedHistory,
|
|
103
120
|
model,
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
stream,
|
|
122
|
+
currentFunctionCalls,
|
|
123
|
+
resolvedUsageDataAccumulator,
|
|
106
124
|
abortSignal,
|
|
107
|
-
|
|
108
|
-
maxFunctionCalls
|
|
125
|
+
onUsageData
|
|
109
126
|
)) as (toolCalls: ChatCompletionMessageToolCall[], currentFunctionCalls: number) => Promise<Readable>;
|
|
110
|
-
const streamProcessor = new OpenAiStreamProcessor(
|
|
127
|
+
const streamProcessor = new OpenAiStreamProcessor(
|
|
128
|
+
inputStream,
|
|
129
|
+
onToolCalls,
|
|
130
|
+
resolvedUsageDataAccumulator,
|
|
131
|
+
this.logLevel,
|
|
132
|
+
abortSignal,
|
|
133
|
+
onUsageData
|
|
134
|
+
);
|
|
111
135
|
return streamProcessor.getOutputStream();
|
|
112
136
|
}
|
|
113
137
|
|
|
114
138
|
const responseMessage = (response as ChatCompletion).choices[0].message;
|
|
115
139
|
if (responseMessage.tool_calls) {
|
|
116
|
-
return await
|
|
140
|
+
return await this.handleToolCalls(
|
|
117
141
|
responseMessage.tool_calls,
|
|
142
|
+
model,
|
|
118
143
|
stream,
|
|
119
144
|
currentFunctionCalls,
|
|
120
|
-
|
|
121
|
-
model,
|
|
122
|
-
functions,
|
|
123
|
-
messageModerators,
|
|
145
|
+
resolvedUsageDataAccumulator,
|
|
124
146
|
abortSignal,
|
|
125
|
-
|
|
126
|
-
maxFunctionCalls
|
|
147
|
+
onUsageData
|
|
127
148
|
);
|
|
128
149
|
}
|
|
129
150
|
|
|
@@ -132,15 +153,11 @@ export class OpenAi {
|
|
|
132
153
|
throw new Error(`Response was empty for messages: ${messages.join('\n')}`);
|
|
133
154
|
}
|
|
134
155
|
|
|
135
|
-
|
|
136
|
-
return responseText;
|
|
156
|
+
this.history.push([responseMessage]);
|
|
157
|
+
return { message: responseText, usagedata: resolvedUsageDataAccumulator.usageData };
|
|
137
158
|
}
|
|
138
159
|
|
|
139
|
-
private
|
|
140
|
-
messages: (string | ChatCompletionMessageParam)[],
|
|
141
|
-
history?: MessageHistory,
|
|
142
|
-
messageModerators?: MessageModerator[]
|
|
143
|
-
) {
|
|
160
|
+
private updateMessageHistory(messages: (string | ChatCompletionMessageParam)[]) {
|
|
144
161
|
const messageParams: ChatCompletionMessageParam[] = messages.map((message) => {
|
|
145
162
|
if (typeof message === 'string') {
|
|
146
163
|
return { role: 'user', content: message };
|
|
@@ -148,69 +165,56 @@ export class OpenAi {
|
|
|
148
165
|
|
|
149
166
|
return message;
|
|
150
167
|
});
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let messageParamsWithHistory = history ? history : new MessageHistory().push(messageParams);
|
|
155
|
-
if (messageModerators) {
|
|
156
|
-
messageParamsWithHistory = OpenAi.moderateHistory(messageParamsWithHistory, messageModerators);
|
|
168
|
+
this.history.push(messageParams);
|
|
169
|
+
if (this.messageModerators) {
|
|
170
|
+
this.moderateHistory(this.history, this.messageModerators);
|
|
157
171
|
}
|
|
158
|
-
|
|
159
|
-
return messageParamsWithHistory;
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
private
|
|
174
|
+
private moderateHistory(history: MessageHistory, messageModerators: MessageModerator[]) {
|
|
163
175
|
for (const messageModerator of messageModerators) {
|
|
164
176
|
history.setMessages(messageModerator.observe(history.getMessages()));
|
|
165
177
|
}
|
|
166
|
-
|
|
167
|
-
return history;
|
|
168
178
|
}
|
|
169
179
|
|
|
170
|
-
private
|
|
171
|
-
|
|
180
|
+
private async executeRequest(
|
|
181
|
+
model: TiktokenModel,
|
|
172
182
|
stream: boolean,
|
|
173
|
-
|
|
174
|
-
functions?: Omit<Function, 'instructions'>[],
|
|
175
|
-
model?: string,
|
|
183
|
+
usageDataAccumulator: UsageDataAccumulator,
|
|
176
184
|
abortSignal?: AbortSignal
|
|
177
185
|
): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {
|
|
178
|
-
const logger = new Logger({ name: 'OpenAi.executeRequest', logLevel });
|
|
186
|
+
const logger = new Logger({ name: 'OpenAi.executeRequest', logLevel: this.logLevel });
|
|
179
187
|
const openaiApi = new OpenAIApi();
|
|
180
188
|
try {
|
|
181
|
-
const latestMessage =
|
|
182
|
-
this.logRequestDetails(logger,
|
|
189
|
+
const latestMessage = this.history.getMessages()[this.history.getMessages().length - 1];
|
|
190
|
+
this.logRequestDetails(logger, latestMessage);
|
|
183
191
|
|
|
184
192
|
const response = await openaiApi.chat.completions.create(
|
|
185
193
|
{
|
|
186
|
-
model
|
|
194
|
+
model,
|
|
187
195
|
temperature: 0,
|
|
188
|
-
messages:
|
|
189
|
-
tools: functions?.map((f) => ({
|
|
196
|
+
messages: this.history.getMessages(),
|
|
197
|
+
tools: this.functions?.map((f) => ({
|
|
190
198
|
type: 'function',
|
|
191
199
|
function: f.definition,
|
|
192
200
|
})),
|
|
193
201
|
stream: stream,
|
|
202
|
+
...(stream && { stream_options: { include_usage: true } }),
|
|
194
203
|
},
|
|
195
204
|
{ signal: abortSignal }
|
|
196
205
|
);
|
|
197
206
|
|
|
198
207
|
if (!stream) {
|
|
199
|
-
this.logResponseDetails(logger, response as ChatCompletion);
|
|
208
|
+
this.logResponseDetails(logger, response as ChatCompletion, usageDataAccumulator);
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
return response;
|
|
203
212
|
} catch (error: any) {
|
|
204
|
-
return this.handleRequestError(logger, error,
|
|
213
|
+
return this.handleRequestError(model, logger, error, stream, usageDataAccumulator, abortSignal);
|
|
205
214
|
}
|
|
206
215
|
}
|
|
207
216
|
|
|
208
|
-
private
|
|
209
|
-
logger: Logger,
|
|
210
|
-
logLevel: LogLevel,
|
|
211
|
-
latestMessage: ChatCompletionMessageParam,
|
|
212
|
-
messageParamsWithHistory: MessageHistory
|
|
213
|
-
) {
|
|
217
|
+
private logRequestDetails(logger: Logger, latestMessage: ChatCompletionMessageParam) {
|
|
214
218
|
if (latestMessage.role == 'tool') {
|
|
215
219
|
logger.info({ message: `Sending request: returning output of tool call (${latestMessage.tool_call_id})` });
|
|
216
220
|
} else if (latestMessage.content) {
|
|
@@ -225,12 +229,10 @@ export class OpenAi {
|
|
|
225
229
|
logger.info({ message: `Sending request` });
|
|
226
230
|
}
|
|
227
231
|
|
|
228
|
-
|
|
229
|
-
logger.debug({ message: `Sending messages:`, obj: { messages: messageParamsWithHistory.getMessages() } });
|
|
230
|
-
}
|
|
232
|
+
logger.debug({ message: `Sending messages:`, obj: { messages: this.history.getMessages() } });
|
|
231
233
|
}
|
|
232
234
|
|
|
233
|
-
private
|
|
235
|
+
private logResponseDetails(logger: Logger, response: ChatCompletion, usageDataAccumulator: UsageDataAccumulator) {
|
|
234
236
|
const responseMessage = response.choices[0].message;
|
|
235
237
|
if (responseMessage.content) {
|
|
236
238
|
logger.info({ message: `Received response`, obj: { response: responseMessage.content } });
|
|
@@ -244,19 +246,23 @@ export class OpenAi {
|
|
|
244
246
|
}
|
|
245
247
|
if (response.usage) {
|
|
246
248
|
logger.info({ message: `Usage data`, obj: { usageData: response.usage } });
|
|
249
|
+
usageDataAccumulator.addTokenUsage({
|
|
250
|
+
promptTokens: response.usage.prompt_tokens,
|
|
251
|
+
completionTokens: response.usage.completion_tokens,
|
|
252
|
+
totalTokens: response.usage.total_tokens,
|
|
253
|
+
});
|
|
247
254
|
} else {
|
|
248
255
|
logger.info({ message: `Usage data missing` });
|
|
249
256
|
}
|
|
250
257
|
}
|
|
251
258
|
|
|
252
|
-
private
|
|
259
|
+
private async handleRequestError(
|
|
260
|
+
model: TiktokenModel,
|
|
253
261
|
logger: Logger,
|
|
254
262
|
error: any,
|
|
255
|
-
messageParamsWithHistory: MessageHistory,
|
|
256
263
|
stream: boolean,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
model?: string
|
|
264
|
+
usageDataAccumulator: UsageDataAccumulator,
|
|
265
|
+
abortSignal?: AbortSignal
|
|
260
266
|
): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {
|
|
261
267
|
if (error.type) {
|
|
262
268
|
logger.info({ message: `Received error response, error type: ${error.type}` });
|
|
@@ -267,29 +273,27 @@ export class OpenAi {
|
|
|
267
273
|
const remainingTokens = error.headers['x-ratelimit-remaining-tokens'];
|
|
268
274
|
const delayMs = 15000;
|
|
269
275
|
logger.warn({
|
|
270
|
-
message: `Waiting to retry
|
|
276
|
+
message: `Waiting to retry due to throttling`,
|
|
277
|
+
obj: { retryDelay: `${delayMs / 1000}s`, tokenResetWaitTime: `${waitTime}s`, remainingTokens },
|
|
271
278
|
});
|
|
272
279
|
await delay(delayMs);
|
|
273
|
-
return await
|
|
280
|
+
return await this.executeRequest(model, stream, usageDataAccumulator, abortSignal);
|
|
274
281
|
}
|
|
275
282
|
}
|
|
276
283
|
throw error;
|
|
277
284
|
}
|
|
278
285
|
|
|
279
|
-
private
|
|
286
|
+
private async handleToolCalls(
|
|
280
287
|
toolCalls: ChatCompletionMessageToolCall[],
|
|
288
|
+
model: TiktokenModel,
|
|
281
289
|
stream: boolean,
|
|
282
290
|
currentFunctionCalls: number,
|
|
283
|
-
|
|
284
|
-
model?: string,
|
|
285
|
-
functions?: Omit<Function, 'instructions'>[],
|
|
286
|
-
messageModerators?: MessageModerator[],
|
|
291
|
+
usageDataAccumulator: UsageDataAccumulator,
|
|
287
292
|
abortSignal?: AbortSignal,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
throw new Error(`Max function calls (${maxFunctionCalls}) reached. Stopping execution.`);
|
|
293
|
+
onUsageData?: (usageData: UsageData) => Promise<void>
|
|
294
|
+
): Promise<GenerateResponseReturn | Readable> {
|
|
295
|
+
if (currentFunctionCalls >= this.maxFunctionCalls) {
|
|
296
|
+
throw new Error(`Max function calls (${this.maxFunctionCalls}) reached. Stopping execution.`);
|
|
293
297
|
}
|
|
294
298
|
|
|
295
299
|
// Create a message for the tool calls
|
|
@@ -300,60 +304,53 @@ export class OpenAi {
|
|
|
300
304
|
};
|
|
301
305
|
|
|
302
306
|
// Add the tool call message to the history
|
|
303
|
-
history.push([toolCallMessage]);
|
|
307
|
+
this.history.push([toolCallMessage]);
|
|
304
308
|
|
|
305
309
|
// Call the tools and get the responses
|
|
306
|
-
const toolMessageParams = await this.callTools(
|
|
310
|
+
const toolMessageParams = await this.callTools(toolCalls, usageDataAccumulator);
|
|
307
311
|
|
|
308
312
|
// Add the tool responses to the history
|
|
309
|
-
history.push(toolMessageParams);
|
|
313
|
+
this.history.push(toolMessageParams);
|
|
310
314
|
|
|
311
315
|
// Generate the next response
|
|
312
|
-
return this.generateResponseHelper(
|
|
313
|
-
[],
|
|
314
|
-
stream,
|
|
315
|
-
currentFunctionCalls + toolCalls.length,
|
|
316
|
+
return this.generateResponseHelper({
|
|
317
|
+
messages: [],
|
|
316
318
|
model,
|
|
317
|
-
|
|
318
|
-
functions,
|
|
319
|
-
messageModerators,
|
|
319
|
+
stream,
|
|
320
320
|
abortSignal,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
321
|
+
onUsageData,
|
|
322
|
+
usageDataAccumulator,
|
|
323
|
+
currentFunctionCalls: currentFunctionCalls + toolCalls.length,
|
|
324
|
+
});
|
|
324
325
|
}
|
|
325
326
|
|
|
326
|
-
private
|
|
327
|
-
logLevel: LogLevel,
|
|
327
|
+
private async callTools(
|
|
328
328
|
toolCalls: ChatCompletionMessageToolCall[],
|
|
329
|
-
|
|
329
|
+
usageDataAccumulator: UsageDataAccumulator
|
|
330
330
|
): Promise<ChatCompletionMessageParam[]> {
|
|
331
331
|
const toolMessageParams: ChatCompletionMessageParam[] = (
|
|
332
332
|
await Promise.all(
|
|
333
|
-
toolCalls.map(
|
|
334
|
-
async (toolCall) => await OpenAi.callFunction(logLevel, toolCall.function, toolCall.id, functions)
|
|
335
|
-
)
|
|
333
|
+
toolCalls.map(async (toolCall) => await this.callFunction(toolCall.function, toolCall.id, usageDataAccumulator))
|
|
336
334
|
)
|
|
337
335
|
).reduce((acc, val) => acc.concat(val), []);
|
|
338
336
|
|
|
339
337
|
return toolMessageParams;
|
|
340
338
|
}
|
|
341
339
|
|
|
342
|
-
private
|
|
343
|
-
logLevel: LogLevel,
|
|
340
|
+
private async callFunction(
|
|
344
341
|
functionCall: ChatCompletionMessageToolCall.Function,
|
|
345
342
|
toolCallId: string,
|
|
346
|
-
|
|
343
|
+
usageDataAccumulator: UsageDataAccumulator
|
|
347
344
|
): Promise<ChatCompletionMessageParam[]> {
|
|
348
|
-
const logger = new Logger({ name: 'OpenAi.callFunction', logLevel });
|
|
349
|
-
if (!functions) {
|
|
345
|
+
const logger = new Logger({ name: 'OpenAi.callFunction', logLevel: this.logLevel });
|
|
346
|
+
if (!this.functions) {
|
|
350
347
|
const errorMessage = `Assistant attempted to call a function when no functions were provided`;
|
|
351
348
|
logger.error({ message: errorMessage });
|
|
352
349
|
return [{ role: 'tool', tool_call_id: toolCallId, content: JSON.stringify({ error: errorMessage }) }];
|
|
353
350
|
}
|
|
354
351
|
|
|
355
352
|
functionCall.name = functionCall.name.split('.').pop() as string;
|
|
356
|
-
const f = functions.find((f) => f.definition.name === functionCall.name);
|
|
353
|
+
const f = this.functions.find((f) => f.definition.name === functionCall.name);
|
|
357
354
|
if (!f) {
|
|
358
355
|
const errorMessage = `Assistant attempted to call nonexistent function`;
|
|
359
356
|
logger.error({ message: errorMessage, obj: { functionName: functionCall.name } });
|
|
@@ -372,6 +369,7 @@ export class OpenAi {
|
|
|
372
369
|
message: `Assistant calling function: (${toolCallId}) ${f.definition.name}`,
|
|
373
370
|
obj: { toolCallId, functionName: f.definition.name, args: parsedArguments },
|
|
374
371
|
});
|
|
372
|
+
usageDataAccumulator.recordToolCall(f.definition.name);
|
|
375
373
|
const returnObject = await f.call(parsedArguments);
|
|
376
374
|
|
|
377
375
|
const returnObjectCompletionParams: ChatCompletionMessageParam[] = [];
|
|
@@ -424,15 +422,15 @@ export class OpenAi {
|
|
|
424
422
|
}
|
|
425
423
|
}
|
|
426
424
|
|
|
427
|
-
|
|
428
|
-
messages
|
|
429
|
-
model
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
) {
|
|
425
|
+
async generateCode({
|
|
426
|
+
messages,
|
|
427
|
+
model,
|
|
428
|
+
includeSystemMessages = true,
|
|
429
|
+
}: {
|
|
430
|
+
messages: (string | ChatCompletionMessageParam)[];
|
|
431
|
+
model?: TiktokenModel;
|
|
432
|
+
includeSystemMessages?: boolean;
|
|
433
|
+
}) {
|
|
436
434
|
const systemMessages: ChatCompletionMessageParam[] = [
|
|
437
435
|
{
|
|
438
436
|
role: 'system',
|
|
@@ -443,36 +441,29 @@ export class OpenAi {
|
|
|
443
441
|
{ role: 'system', content: 'Export all functions and objects generated.' },
|
|
444
442
|
{ role: 'system', content: 'Do not omit function implementations.' },
|
|
445
443
|
];
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
? new MessageHistory().push(systemMessages)
|
|
452
|
-
: undefined;
|
|
453
|
-
const code = await this.generateResponse(messages, model, resolvedHistory, functions, messageModerators, logLevel);
|
|
454
|
-
return this.parseCodeFromMarkdown(code);
|
|
444
|
+
if (includeSystemMessages) {
|
|
445
|
+
this.history.push(systemMessages);
|
|
446
|
+
}
|
|
447
|
+
const { message } = await this.generateResponse({ messages, model });
|
|
448
|
+
return OpenAi.parseCodeFromMarkdown(message);
|
|
455
449
|
}
|
|
456
450
|
|
|
457
|
-
|
|
458
|
-
code
|
|
459
|
-
description
|
|
460
|
-
model
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
451
|
+
async updateCode({
|
|
452
|
+
code,
|
|
453
|
+
description,
|
|
454
|
+
model,
|
|
455
|
+
includeSystemMessages = true,
|
|
456
|
+
}: {
|
|
457
|
+
code: string;
|
|
458
|
+
description: string;
|
|
459
|
+
model?: TiktokenModel;
|
|
460
|
+
includeSystemMessages?: boolean;
|
|
461
|
+
}) {
|
|
462
|
+
return await this.generateCode({
|
|
463
|
+
messages: [OpenAi.updateCodeDescription(code, description)],
|
|
469
464
|
model,
|
|
470
|
-
history,
|
|
471
|
-
functions,
|
|
472
|
-
messageModerators,
|
|
473
465
|
includeSystemMessages,
|
|
474
|
-
|
|
475
|
-
);
|
|
466
|
+
});
|
|
476
467
|
}
|
|
477
468
|
|
|
478
469
|
static updateCodeDescription(code: string, description: string) {
|
|
@@ -508,15 +499,15 @@ export class OpenAi {
|
|
|
508
499
|
return filteredLines.join('\n');
|
|
509
500
|
}
|
|
510
501
|
|
|
511
|
-
|
|
512
|
-
messages
|
|
513
|
-
model
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
): Promise<string[]> {
|
|
502
|
+
async generateList({
|
|
503
|
+
messages,
|
|
504
|
+
model,
|
|
505
|
+
includeSystemMessages = true,
|
|
506
|
+
}: {
|
|
507
|
+
messages: (string | ChatCompletionMessageParam)[];
|
|
508
|
+
model?: TiktokenModel;
|
|
509
|
+
includeSystemMessages?: boolean;
|
|
510
|
+
}): Promise<string[]> {
|
|
520
511
|
const systemMessages: ChatCompletionMessageParam[] = [
|
|
521
512
|
{
|
|
522
513
|
role: 'system',
|
|
@@ -524,14 +515,10 @@ export class OpenAi {
|
|
|
524
515
|
},
|
|
525
516
|
{ role: 'system', content: 'Separate each item in the list by a ;' },
|
|
526
517
|
];
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
? new MessageHistory().push(systemMessages)
|
|
533
|
-
: undefined;
|
|
534
|
-
const list = await this.generateResponse(messages, model, resolvedHistory, functions, messageModerators, logLevel);
|
|
535
|
-
return list.split(';').map((item) => item.trim());
|
|
518
|
+
if (includeSystemMessages) {
|
|
519
|
+
this.history.push(systemMessages);
|
|
520
|
+
}
|
|
521
|
+
const { message } = await this.generateResponse({ messages, model });
|
|
522
|
+
return message.split(';').map((item) => item.trim());
|
|
536
523
|
}
|
|
537
524
|
}
|