@agentica/core 0.44.1 → 0.45.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/lib/events/AgenticaCallEvent.d.ts +2 -1
- package/lib/events/AgenticaCancelEvent.d.ts +2 -1
- package/lib/events/AgenticaExecuteEvent.d.ts +2 -1
- package/lib/events/AgenticaSelectEvent.d.ts +2 -1
- package/lib/factory/events.d.ts +5 -0
- package/lib/factory/events.js +9 -0
- package/lib/factory/events.js.map +1 -1
- package/lib/factory/histories.js +11 -4
- package/lib/factory/histories.js.map +1 -1
- package/lib/factory/histories.spec.d.ts +1 -0
- package/lib/factory/histories.spec.js +34 -0
- package/lib/factory/histories.spec.js.map +1 -0
- package/lib/histories/AgenticaCancelHistory.d.ts +2 -1
- package/lib/histories/AgenticaExecuteHistory.d.ts +2 -1
- package/lib/histories/AgenticaSelectHistory.d.ts +2 -1
- package/lib/histories/contents/AgenticaCallReasoningPayload.d.ts +26 -0
- package/lib/histories/contents/AgenticaCallReasoningPayload.js +3 -0
- package/lib/histories/contents/AgenticaCallReasoningPayload.js.map +1 -0
- package/lib/histories/contents/index.d.ts +1 -0
- package/lib/histories/contents/index.js +1 -0
- package/lib/histories/contents/index.js.map +1 -1
- package/lib/index.mjs +136 -49
- package/lib/index.mjs.map +1 -1
- package/lib/json/IAgenticaEventJson.d.ts +5 -4
- package/lib/json/IAgenticaHistoryJson.d.ts +4 -3
- package/lib/orchestrate/call.js +27 -11
- package/lib/orchestrate/call.js.map +1 -1
- package/lib/orchestrate/cancel.js +3 -1
- package/lib/orchestrate/cancel.js.map +1 -1
- package/lib/orchestrate/internal/cancelFunctionFromContext.js +2 -1
- package/lib/orchestrate/internal/cancelFunctionFromContext.js.map +1 -1
- package/lib/orchestrate/internal/selectFunctionFromContext.js +2 -1
- package/lib/orchestrate/internal/selectFunctionFromContext.js.map +1 -1
- package/lib/orchestrate/select.js +3 -1
- package/lib/orchestrate/select.js.map +1 -1
- package/lib/transformers/transformHistory.js +3 -0
- package/lib/transformers/transformHistory.js.map +1 -1
- package/lib/utils/ChatGptAssistantMessageUtil.d.ts +10 -0
- package/lib/utils/ChatGptAssistantMessageUtil.js +36 -0
- package/lib/utils/ChatGptAssistantMessageUtil.js.map +1 -0
- package/lib/utils/ChatGptCompletionMessageUtil.js +33 -15
- package/lib/utils/ChatGptCompletionMessageUtil.js.map +1 -1
- package/lib/utils/ChatGptCompletionMessageUtil.spec.js +27 -0
- package/lib/utils/ChatGptCompletionMessageUtil.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/events/AgenticaCallEvent.ts +2 -1
- package/src/events/AgenticaCancelEvent.ts +2 -1
- package/src/events/AgenticaExecuteEvent.ts +2 -1
- package/src/events/AgenticaSelectEvent.ts +2 -1
- package/src/factory/events.ts +14 -0
- package/src/factory/histories.spec.ts +34 -0
- package/src/factory/histories.ts +16 -4
- package/src/histories/AgenticaCancelHistory.ts +2 -1
- package/src/histories/AgenticaExecuteHistory.ts +2 -1
- package/src/histories/AgenticaSelectHistory.ts +2 -1
- package/src/histories/contents/AgenticaCallReasoningPayload.ts +26 -0
- package/src/histories/contents/index.ts +1 -0
- package/src/json/IAgenticaEventJson.ts +5 -4
- package/src/json/IAgenticaHistoryJson.ts +4 -3
- package/src/orchestrate/call.ts +28 -4
- package/src/orchestrate/cancel.ts +7 -1
- package/src/orchestrate/internal/cancelFunctionFromContext.ts +3 -0
- package/src/orchestrate/internal/selectFunctionFromContext.ts +3 -0
- package/src/orchestrate/select.ts +7 -1
- package/src/transformers/transformHistory.ts +3 -0
- package/src/utils/ChatGptAssistantMessageUtil.ts +47 -0
- package/src/utils/ChatGptCompletionMessageUtil.spec.ts +30 -0
- package/src/utils/ChatGptCompletionMessageUtil.ts +31 -15
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { tags } from "typia";
|
|
2
2
|
|
|
3
3
|
import type { AgenticaUserMessageContent } from "../histories";
|
|
4
|
+
import type { AgenticaCallReasoningPayload } from "../histories/contents/AgenticaCallReasoningPayload";
|
|
4
5
|
|
|
5
6
|
import type { IAgenticaOperationJson } from "./IAgenticaOperationJson";
|
|
6
7
|
import type { IAgenticaOperationSelectionJson } from "./IAgenticaOperationSelectionJson";
|
|
@@ -78,7 +79,7 @@ export namespace IAgenticaHistoryJson {
|
|
|
78
79
|
*
|
|
79
80
|
* Selection prompt about candidate functions to call.
|
|
80
81
|
*/
|
|
81
|
-
export interface ISelect extends IBase<"select"
|
|
82
|
+
export interface ISelect extends IBase<"select">, AgenticaCallReasoningPayload {
|
|
82
83
|
/**
|
|
83
84
|
* Operations that have been selected.
|
|
84
85
|
*/
|
|
@@ -90,7 +91,7 @@ export namespace IAgenticaHistoryJson {
|
|
|
90
91
|
*
|
|
91
92
|
* Cancellation prompt about the candidate functions to be discarded.
|
|
92
93
|
*/
|
|
93
|
-
export interface ICancel extends IBase<"cancel"
|
|
94
|
+
export interface ICancel extends IBase<"cancel">, AgenticaCallReasoningPayload {
|
|
94
95
|
/**
|
|
95
96
|
* Operations that have been cancelled.
|
|
96
97
|
*/
|
|
@@ -102,7 +103,7 @@ export namespace IAgenticaHistoryJson {
|
|
|
102
103
|
*
|
|
103
104
|
* Execution prompt about the LLM function calling.
|
|
104
105
|
*/
|
|
105
|
-
export interface IExecute extends IBase<"execute"
|
|
106
|
+
export interface IExecute extends IBase<"execute">, AgenticaCallReasoningPayload {
|
|
106
107
|
/**
|
|
107
108
|
* Target operation to call.
|
|
108
109
|
*/
|
package/src/orchestrate/call.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type { AgenticaAssistantMessageEvent, AgenticaValidateEvent } from "../ev
|
|
|
14
14
|
import type { AgenticaCallEvent } from "../events/AgenticaCallEvent";
|
|
15
15
|
import type { AgenticaExecuteEvent } from "../events/AgenticaExecuteEvent";
|
|
16
16
|
import type { AgenticaJsonParseErrorEvent } from "../events/AgenticaJsonParseErrorEvent";
|
|
17
|
+
import type { AgenticaCallReasoningPayload } from "../histories/contents/AgenticaCallReasoningPayload";
|
|
17
18
|
import type { MicroAgenticaHistory } from "../histories/MicroAgenticaHistory";
|
|
18
19
|
|
|
19
20
|
import { AgenticaConstant } from "../constants/AgenticaConstant";
|
|
@@ -26,6 +27,7 @@ import { createAssistantMessageEvent, createCallEvent, createExecuteEvent, creat
|
|
|
26
27
|
import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
|
|
27
28
|
import { __get_retry } from "../utils/__retry";
|
|
28
29
|
import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
|
|
30
|
+
import { ChatGptAssistantMessageUtil } from "../utils/ChatGptAssistantMessageUtil";
|
|
29
31
|
import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
|
|
30
32
|
import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
|
|
31
33
|
import { StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
|
|
@@ -133,6 +135,10 @@ export async function call(
|
|
|
133
135
|
|
|
134
136
|
const retry: number = ctx.config?.retry ?? AgenticaConstant.RETRY;
|
|
135
137
|
for (const choice of (completion.choices ?? [])) {
|
|
138
|
+
const assistant = ChatGptAssistantMessageUtil.collect(choice.message);
|
|
139
|
+
const reasoning: AgenticaCallReasoningPayload | undefined = assistant === undefined
|
|
140
|
+
? undefined
|
|
141
|
+
: { assistant };
|
|
136
142
|
for (const tc of choice.message.tool_calls ?? []) {
|
|
137
143
|
if (tc.type === "function") {
|
|
138
144
|
const operation: AgenticaOperation | undefined = operations.find(
|
|
@@ -145,6 +151,7 @@ export async function call(
|
|
|
145
151
|
ctx,
|
|
146
152
|
operation,
|
|
147
153
|
tc,
|
|
154
|
+
reasoning,
|
|
148
155
|
[],
|
|
149
156
|
retry,
|
|
150
157
|
);
|
|
@@ -166,6 +173,7 @@ async function predicate(
|
|
|
166
173
|
ctx: AgenticaContext | MicroAgenticaContext,
|
|
167
174
|
operation: AgenticaOperation,
|
|
168
175
|
toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
|
|
176
|
+
reasoning: AgenticaCallReasoningPayload | undefined,
|
|
169
177
|
previousValidationErrors: AgenticaValidateEvent[],
|
|
170
178
|
life: number,
|
|
171
179
|
): Promise<AgenticaExecuteEvent> {
|
|
@@ -174,11 +182,12 @@ async function predicate(
|
|
|
174
182
|
= parseArguments(
|
|
175
183
|
operation,
|
|
176
184
|
toolCall,
|
|
185
|
+
reasoning,
|
|
177
186
|
life,
|
|
178
187
|
);
|
|
179
188
|
await ctx.dispatch(call);
|
|
180
189
|
if (call.type === "jsonParseError") {
|
|
181
|
-
return correctJsonError(ctx, toolCall, call, previousValidationErrors, life - 1);
|
|
190
|
+
return correctJsonError(ctx, toolCall, reasoning, call, previousValidationErrors, life - 1);
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
// CHECK TYPE VALIDATION
|
|
@@ -224,11 +233,13 @@ async function correctTypeError(
|
|
|
224
233
|
errors: validateEvent.result.errors,
|
|
225
234
|
}),
|
|
226
235
|
success: false,
|
|
236
|
+
assistant: callEvent.assistant,
|
|
227
237
|
}),
|
|
228
238
|
operation: callEvent.operation,
|
|
229
239
|
toolCall: {
|
|
230
240
|
id: callEvent.id,
|
|
231
241
|
arguments: JSON.stringify(callEvent.arguments),
|
|
242
|
+
assistant: callEvent.assistant,
|
|
232
243
|
result: [
|
|
233
244
|
"🚨 VALIDATION FAILURE: Your function arguments do not conform to the required schema.",
|
|
234
245
|
"",
|
|
@@ -269,6 +280,7 @@ async function correctTypeError(
|
|
|
269
280
|
async function correctJsonError(
|
|
270
281
|
ctx: AgenticaContext | MicroAgenticaContext,
|
|
271
282
|
toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
|
|
283
|
+
reasoning: AgenticaCallReasoningPayload | undefined,
|
|
272
284
|
parseErrorEvent: AgenticaJsonParseErrorEvent,
|
|
273
285
|
previousValidationErrors: AgenticaValidateEvent[],
|
|
274
286
|
life: number,
|
|
@@ -280,11 +292,13 @@ async function correctJsonError(
|
|
|
280
292
|
arguments: {},
|
|
281
293
|
value: new AgenticaJsonParseError(parseErrorEvent.failure),
|
|
282
294
|
success: false,
|
|
295
|
+
assistant: reasoning?.assistant,
|
|
283
296
|
}),
|
|
284
297
|
operation: parseErrorEvent.operation,
|
|
285
298
|
toolCall: {
|
|
286
299
|
id: parseErrorEvent.id,
|
|
287
300
|
arguments: parseErrorEvent.failure.input,
|
|
301
|
+
assistant: reasoning?.assistant,
|
|
288
302
|
result: dedent`
|
|
289
303
|
Invalid JSON format.
|
|
290
304
|
|
|
@@ -316,6 +330,7 @@ async function correctJsonError(
|
|
|
316
330
|
function parseArguments(
|
|
317
331
|
operation: AgenticaOperation,
|
|
318
332
|
toolCall: OpenAI.ChatCompletionMessageFunctionToolCall,
|
|
333
|
+
reasoning: AgenticaCallReasoningPayload | undefined,
|
|
319
334
|
life: number,
|
|
320
335
|
): AgenticaCallEvent | AgenticaJsonParseErrorEvent {
|
|
321
336
|
const result: IJsonParseResult<Record<string, unknown>> = operation.function.parse(
|
|
@@ -333,6 +348,7 @@ function parseArguments(
|
|
|
333
348
|
id: toolCall.id,
|
|
334
349
|
operation,
|
|
335
350
|
arguments: result.data,
|
|
351
|
+
assistant: reasoning?.assistant,
|
|
336
352
|
});
|
|
337
353
|
}
|
|
338
354
|
|
|
@@ -344,6 +360,7 @@ async function correctError(
|
|
|
344
360
|
toolCall: {
|
|
345
361
|
id: string;
|
|
346
362
|
arguments: string;
|
|
363
|
+
assistant?: AgenticaCallReasoningPayload["assistant"];
|
|
347
364
|
result: string;
|
|
348
365
|
};
|
|
349
366
|
systemPrompt: string;
|
|
@@ -371,7 +388,7 @@ async function correctError(
|
|
|
371
388
|
ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory[])
|
|
372
389
|
?? AgenticaSystemPrompt.EXECUTE,
|
|
373
390
|
},
|
|
374
|
-
{
|
|
391
|
+
ChatGptAssistantMessageUtil.assign({
|
|
375
392
|
role: "assistant",
|
|
376
393
|
tool_calls: [
|
|
377
394
|
{
|
|
@@ -383,7 +400,7 @@ async function correctError(
|
|
|
383
400
|
},
|
|
384
401
|
} satisfies OpenAI.ChatCompletionMessageFunctionToolCall,
|
|
385
402
|
],
|
|
386
|
-
} satisfies OpenAI.ChatCompletionAssistantMessageParam,
|
|
403
|
+
} satisfies OpenAI.ChatCompletionAssistantMessageParam, props.toolCall.assistant),
|
|
387
404
|
{
|
|
388
405
|
role: "tool",
|
|
389
406
|
content: props.toolCall.result,
|
|
@@ -425,7 +442,8 @@ async function correctError(
|
|
|
425
442
|
return ChatGptCompletionMessageUtil.merge(await StreamUtil.readAll(result.value));
|
|
426
443
|
})();
|
|
427
444
|
|
|
428
|
-
const
|
|
445
|
+
const choice = completion.choices?.[0];
|
|
446
|
+
const toolCall: OpenAI.ChatCompletionMessageFunctionToolCall | undefined = choice?.message.tool_calls?.filter(
|
|
429
447
|
tc => tc.type === "function",
|
|
430
448
|
).find(
|
|
431
449
|
s => s.function.name === props.operation.name,
|
|
@@ -437,10 +455,14 @@ async function correctError(
|
|
|
437
455
|
life: props.life - 1,
|
|
438
456
|
});
|
|
439
457
|
}
|
|
458
|
+
const assistant = choice === undefined
|
|
459
|
+
? undefined
|
|
460
|
+
: ChatGptAssistantMessageUtil.collect(choice.message);
|
|
440
461
|
return predicate(
|
|
441
462
|
ctx,
|
|
442
463
|
props.operation,
|
|
443
464
|
toolCall,
|
|
465
|
+
assistant === undefined ? undefined : { assistant },
|
|
444
466
|
props.previousValidationErrors,
|
|
445
467
|
props.life,
|
|
446
468
|
);
|
|
@@ -473,6 +495,7 @@ async function executeFunction(
|
|
|
473
495
|
arguments: call.arguments,
|
|
474
496
|
value,
|
|
475
497
|
success: true,
|
|
498
|
+
assistant: call.assistant,
|
|
476
499
|
});
|
|
477
500
|
}
|
|
478
501
|
catch (error) {
|
|
@@ -489,6 +512,7 @@ async function executeFunction(
|
|
|
489
512
|
}
|
|
490
513
|
: error,
|
|
491
514
|
success: false,
|
|
515
|
+
assistant: call.assistant,
|
|
492
516
|
});
|
|
493
517
|
}
|
|
494
518
|
}
|
|
@@ -15,6 +15,7 @@ import { AgenticaConstant } from "../constants/AgenticaConstant";
|
|
|
15
15
|
import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
|
|
16
16
|
import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
|
|
17
17
|
import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
|
|
18
|
+
import { ChatGptAssistantMessageUtil } from "../utils/ChatGptAssistantMessageUtil";
|
|
18
19
|
import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
|
|
19
20
|
import { StreamUtil } from "../utils/StreamUtil";
|
|
20
21
|
|
|
@@ -205,6 +206,7 @@ async function step(
|
|
|
205
206
|
// PROCESS COMPLETION
|
|
206
207
|
// ----
|
|
207
208
|
for (const choice of (completion.choices ?? [])) {
|
|
209
|
+
const assistant = ChatGptAssistantMessageUtil.collect(choice.message);
|
|
208
210
|
// TOOL CALLING HANDLER
|
|
209
211
|
if (choice.message.tool_calls != null) {
|
|
210
212
|
for (const tc of choice.message.tool_calls) {
|
|
@@ -224,7 +226,11 @@ async function step(
|
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
for (const reference of input.functions) {
|
|
227
|
-
cancelFunctionFromContext(
|
|
229
|
+
cancelFunctionFromContext(
|
|
230
|
+
ctx,
|
|
231
|
+
reference,
|
|
232
|
+
assistant === undefined ? undefined : { assistant },
|
|
233
|
+
);
|
|
228
234
|
}
|
|
229
235
|
}
|
|
230
236
|
}
|
|
@@ -2,6 +2,7 @@ import type { AgenticaContext } from "../../context/AgenticaContext";
|
|
|
2
2
|
import type { AgenticaOperationSelection } from "../../context/AgenticaOperationSelection";
|
|
3
3
|
import type { __IChatFunctionReference } from "../../context/internal/__IChatFunctionReference";
|
|
4
4
|
import type { AgenticaCancelEvent } from "../../events";
|
|
5
|
+
import type { AgenticaCallReasoningPayload } from "../../histories/contents/AgenticaCallReasoningPayload";
|
|
5
6
|
|
|
6
7
|
import { createCancelEvent } from "../../factory/events";
|
|
7
8
|
import { createOperationSelection } from "../../factory/operations";
|
|
@@ -12,6 +13,7 @@ import { createOperationSelection } from "../../factory/operations";
|
|
|
12
13
|
export function cancelFunctionFromContext(
|
|
13
14
|
ctx: AgenticaContext,
|
|
14
15
|
reference: __IChatFunctionReference,
|
|
16
|
+
reasoning?: AgenticaCallReasoningPayload,
|
|
15
17
|
): void {
|
|
16
18
|
const index: number = ctx.stack.findIndex(
|
|
17
19
|
item => item.operation.name === reference.name,
|
|
@@ -28,6 +30,7 @@ export function cancelFunctionFromContext(
|
|
|
28
30
|
operation: item.operation,
|
|
29
31
|
reason: reference.reason,
|
|
30
32
|
}),
|
|
33
|
+
assistant: reasoning?.assistant,
|
|
31
34
|
});
|
|
32
35
|
void ctx.dispatch(event).catch(() => {});
|
|
33
36
|
}
|
|
@@ -3,6 +3,7 @@ import type { AgenticaOperation } from "../../context/AgenticaOperation";
|
|
|
3
3
|
import type { AgenticaOperationSelection } from "../../context/AgenticaOperationSelection";
|
|
4
4
|
import type { __IChatFunctionReference } from "../../context/internal/__IChatFunctionReference";
|
|
5
5
|
import type { AgenticaSelectEvent } from "../../events/AgenticaSelectEvent";
|
|
6
|
+
import type { AgenticaCallReasoningPayload } from "../../histories/contents/AgenticaCallReasoningPayload";
|
|
6
7
|
|
|
7
8
|
import { createSelectEvent } from "../../factory/events";
|
|
8
9
|
import { createOperationSelection } from "../../factory/operations";
|
|
@@ -13,6 +14,7 @@ import { createOperationSelection } from "../../factory/operations";
|
|
|
13
14
|
export function selectFunctionFromContext(
|
|
14
15
|
ctx: AgenticaContext,
|
|
15
16
|
reference: __IChatFunctionReference,
|
|
17
|
+
reasoning?: AgenticaCallReasoningPayload,
|
|
16
18
|
): void {
|
|
17
19
|
const operation: AgenticaOperation | undefined
|
|
18
20
|
= ctx.operations.flat.get(reference.name);
|
|
@@ -29,6 +31,7 @@ export function selectFunctionFromContext(
|
|
|
29
31
|
|
|
30
32
|
const event: AgenticaSelectEvent = createSelectEvent({
|
|
31
33
|
selection,
|
|
34
|
+
assistant: reasoning?.assistant,
|
|
32
35
|
});
|
|
33
36
|
void ctx.dispatch(event).catch(() => {});
|
|
34
37
|
}
|
|
@@ -18,6 +18,7 @@ import { createAssistantMessageEvent } from "../factory/events";
|
|
|
18
18
|
import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
|
|
19
19
|
import { __get_retry } from "../utils/__retry";
|
|
20
20
|
import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
|
|
21
|
+
import { ChatGptAssistantMessageUtil } from "../utils/ChatGptAssistantMessageUtil";
|
|
21
22
|
import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
|
|
22
23
|
import { toAsyncGenerator } from "../utils/StreamUtil";
|
|
23
24
|
|
|
@@ -261,6 +262,7 @@ async function step(
|
|
|
261
262
|
// PROCESS COMPLETION
|
|
262
263
|
// ----
|
|
263
264
|
for (const choice of (completion.choices ?? [])) {
|
|
265
|
+
const assistant = ChatGptAssistantMessageUtil.collect(choice.message);
|
|
264
266
|
// FUNCTION CALLING
|
|
265
267
|
if (choice.message.tool_calls != null) {
|
|
266
268
|
for (const tc of choice.message.tool_calls) {
|
|
@@ -279,7 +281,11 @@ async function step(
|
|
|
279
281
|
continue;
|
|
280
282
|
}
|
|
281
283
|
for (const reference of input.functions) {
|
|
282
|
-
selectFunctionFromContext(
|
|
284
|
+
selectFunctionFromContext(
|
|
285
|
+
ctx,
|
|
286
|
+
reference,
|
|
287
|
+
assistant === undefined ? undefined : { assistant },
|
|
288
|
+
);
|
|
283
289
|
}
|
|
284
290
|
}
|
|
285
291
|
}
|
|
@@ -95,6 +95,7 @@ function transformSelect(props: {
|
|
|
95
95
|
}),
|
|
96
96
|
reason: props.history.selection.reason,
|
|
97
97
|
}),
|
|
98
|
+
assistant: props.history.assistant,
|
|
98
99
|
});
|
|
99
100
|
}
|
|
100
101
|
|
|
@@ -112,6 +113,7 @@ function transformCancel(props: {
|
|
|
112
113
|
}),
|
|
113
114
|
reason: props.history.selection.reason,
|
|
114
115
|
}),
|
|
116
|
+
assistant: props.history.assistant,
|
|
115
117
|
});
|
|
116
118
|
}
|
|
117
119
|
|
|
@@ -133,6 +135,7 @@ function transformExecute(props: {
|
|
|
133
135
|
*/
|
|
134
136
|
value: props.history.value as Record<string, unknown>,
|
|
135
137
|
success: props.history.success,
|
|
138
|
+
assistant: props.history.assistant,
|
|
136
139
|
});
|
|
137
140
|
}
|
|
138
141
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type OpenAI from "openai";
|
|
2
|
+
|
|
3
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return value != null && typeof value === "object" && Array.isArray(value) === false;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function collect(source: unknown): Record<string, unknown> | undefined {
|
|
8
|
+
if (isRecord(source) === false) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const output: Record<string, unknown> = {};
|
|
12
|
+
for (const [key, value] of Object.entries(source)) {
|
|
13
|
+
if (key.startsWith("reasoning") && value !== undefined) {
|
|
14
|
+
output[key] = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return Object.keys(output).length === 0
|
|
18
|
+
? undefined
|
|
19
|
+
: output;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function assign<Message extends OpenAI.ChatCompletionAssistantMessageParam>(
|
|
23
|
+
message: Message,
|
|
24
|
+
payload: Record<string, unknown> | undefined,
|
|
25
|
+
): Message {
|
|
26
|
+
const collected = collect(payload);
|
|
27
|
+
if (collected === undefined) {
|
|
28
|
+
return message;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
...message,
|
|
32
|
+
...collected,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function assignFrom<Message extends OpenAI.ChatCompletionAssistantMessageParam>(
|
|
37
|
+
message: Message,
|
|
38
|
+
source: unknown,
|
|
39
|
+
): Message {
|
|
40
|
+
return assign(message, collect(source));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const ChatGptAssistantMessageUtil = {
|
|
44
|
+
assign,
|
|
45
|
+
assignFrom,
|
|
46
|
+
collect,
|
|
47
|
+
};
|
|
@@ -264,6 +264,36 @@ describe("chatGptCompletionMessageUtil", () => {
|
|
|
264
264
|
const result = ChatGptCompletionMessageUtil.mergeChoice(acc, cur);
|
|
265
265
|
expect(result.message.refusal).toBe("I cannot do that");
|
|
266
266
|
});
|
|
267
|
+
|
|
268
|
+
it("should merge reasoning payloads", () => {
|
|
269
|
+
const acc: ChatCompletion.Choice = {
|
|
270
|
+
index: 0,
|
|
271
|
+
message: {
|
|
272
|
+
role: "assistant",
|
|
273
|
+
content: null,
|
|
274
|
+
reasoning: "think",
|
|
275
|
+
reasoning_content: "deep",
|
|
276
|
+
reasoning_details: [{ index: 0 }],
|
|
277
|
+
} as any,
|
|
278
|
+
} as any;
|
|
279
|
+
|
|
280
|
+
const cur: ChatCompletionChunk.Choice = {
|
|
281
|
+
index: 0,
|
|
282
|
+
delta: {
|
|
283
|
+
reasoning: " more",
|
|
284
|
+
reasoning_content: " seek",
|
|
285
|
+
reasoning_details: [{ index: 1 }],
|
|
286
|
+
} as any,
|
|
287
|
+
} as any;
|
|
288
|
+
|
|
289
|
+
const result = ChatGptCompletionMessageUtil.mergeChoice(acc, cur);
|
|
290
|
+
expect((result.message as { reasoning?: string }).reasoning).toBe("think more");
|
|
291
|
+
expect((result.message as { reasoning_content?: string }).reasoning_content).toBe("deep seek");
|
|
292
|
+
expect((result.message as { reasoning_details?: unknown[] }).reasoning_details).toEqual([
|
|
293
|
+
{ index: 0 },
|
|
294
|
+
{ index: 1 },
|
|
295
|
+
]);
|
|
296
|
+
});
|
|
267
297
|
});
|
|
268
298
|
|
|
269
299
|
describe("mergeToolCalls", () => {
|
|
@@ -11,6 +11,7 @@ import { dedent, LlmJson } from "@typia/utils";
|
|
|
11
11
|
|
|
12
12
|
// import typia from "typia";
|
|
13
13
|
import { ByteArrayUtil } from "./ByteArrayUtil";
|
|
14
|
+
import { ChatGptAssistantMessageUtil } from "./ChatGptAssistantMessageUtil";
|
|
14
15
|
import { ChatGptTokenUsageAggregator } from "./ChatGptTokenUsageAggregator";
|
|
15
16
|
|
|
16
17
|
function transformCompletionChunk(source: string | Uint8Array): ChatCompletionChunk {
|
|
@@ -54,7 +55,7 @@ function accumulate(origin: ChatCompletion, chunk: ChatCompletionChunk): ChatCom
|
|
|
54
55
|
?? (null as unknown as ChatCompletion.Choice["finish_reason"]),
|
|
55
56
|
|
|
56
57
|
logprobs: choice.logprobs ?? null,
|
|
57
|
-
message: {
|
|
58
|
+
message: ChatGptAssistantMessageUtil.assignFrom({
|
|
58
59
|
tool_calls: choice.delta.tool_calls !== undefined
|
|
59
60
|
? choice.delta.tool_calls.reduce((acc, cur) => {
|
|
60
61
|
acc[cur.index] = {
|
|
@@ -71,11 +72,7 @@ function accumulate(origin: ChatCompletion, chunk: ChatCompletionChunk): ChatCom
|
|
|
71
72
|
content: choice.delta.content ?? null,
|
|
72
73
|
refusal: choice.delta.refusal ?? null,
|
|
73
74
|
role: "assistant",
|
|
74
|
-
|
|
75
|
-
// for open router
|
|
76
|
-
reasoning: (choice.delta as { reasoning?: string }).reasoning ?? null,
|
|
77
|
-
}),
|
|
78
|
-
} satisfies ChatCompletionMessage,
|
|
75
|
+
} satisfies ChatCompletionMessage, choice.delta),
|
|
79
76
|
};
|
|
80
77
|
});
|
|
81
78
|
|
|
@@ -154,15 +151,7 @@ function mergeChoice(acc: ChatCompletion.Choice, cur: ChatCompletionChunk.Choice
|
|
|
154
151
|
}
|
|
155
152
|
}
|
|
156
153
|
|
|
157
|
-
|
|
158
|
-
if ((cur.delta as { reasoning?: string }).reasoning != null) {
|
|
159
|
-
if ((acc.message as { reasoning?: string }).reasoning == null) {
|
|
160
|
-
(acc.message as { reasoning?: string }).reasoning = (cur.delta as { reasoning?: string }).reasoning;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
(acc.message as unknown as { reasoning: string }).reasoning += (cur.delta as { reasoning: string }).reasoning;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
154
|
+
mergeAssistantMessagePayload(acc.message, cur.delta);
|
|
166
155
|
|
|
167
156
|
if (cur.delta.tool_calls != null) {
|
|
168
157
|
acc.message.tool_calls ??= [];
|
|
@@ -201,6 +190,33 @@ function mergeToolCalls(acc: ChatCompletionMessageFunctionToolCall, cur: ChatCom
|
|
|
201
190
|
return acc;
|
|
202
191
|
}
|
|
203
192
|
|
|
193
|
+
function mergeAssistantMessagePayload(
|
|
194
|
+
message: ChatCompletionMessage,
|
|
195
|
+
delta: ChatCompletionChunk.Choice.Delta,
|
|
196
|
+
): void {
|
|
197
|
+
const target = message as unknown as Record<string, unknown>;
|
|
198
|
+
const source = delta as Record<string, unknown>;
|
|
199
|
+
for (const [key, value] of Object.entries(source)) {
|
|
200
|
+
if (key.startsWith("reasoning") === false || value === undefined) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (typeof value === "string") {
|
|
204
|
+
target[key] = typeof target[key] === "string"
|
|
205
|
+
? `${target[key]}${value}`
|
|
206
|
+
: value;
|
|
207
|
+
}
|
|
208
|
+
else if (Array.isArray(value)) {
|
|
209
|
+
target[key] = [
|
|
210
|
+
...(Array.isArray(target[key]) ? target[key] : []),
|
|
211
|
+
...value,
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
target[key] = value;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
204
220
|
export const ChatGptCompletionMessageUtil = {
|
|
205
221
|
transformCompletionChunk,
|
|
206
222
|
accumulate,
|