@agentica/core 0.32.2 → 0.32.3-dev.1
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/index.mjs +297 -333
- package/lib/index.mjs.map +1 -1
- package/lib/orchestrate/call.js +87 -107
- package/lib/orchestrate/call.js.map +1 -1
- package/lib/orchestrate/describe.js +5 -50
- package/lib/orchestrate/describe.js.map +1 -1
- package/lib/orchestrate/initialize.js +5 -50
- package/lib/orchestrate/initialize.js.map +1 -1
- package/lib/orchestrate/select.js +107 -126
- package/lib/orchestrate/select.js.map +1 -1
- package/lib/utils/AssistantMessageEmptyError.d.ts +7 -0
- package/lib/utils/AssistantMessageEmptyError.js +17 -0
- package/lib/utils/AssistantMessageEmptyError.js.map +1 -0
- package/lib/utils/ChatGptCompletionStreamingUtil.d.ts +8 -0
- package/lib/utils/ChatGptCompletionStreamingUtil.js +74 -0
- package/lib/utils/ChatGptCompletionStreamingUtil.js.map +1 -0
- package/lib/utils/__retry.d.ts +1 -0
- package/lib/utils/__retry.js +30 -0
- package/lib/utils/__retry.js.map +1 -0
- package/lib/utils/__retry.spec.d.ts +1 -0
- package/lib/utils/__retry.spec.js +172 -0
- package/lib/utils/__retry.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/orchestrate/call.ts +88 -114
- package/src/orchestrate/describe.ts +7 -65
- package/src/orchestrate/initialize.ts +4 -64
- package/src/orchestrate/select.ts +111 -138
- package/src/utils/AssistantMessageEmptyError.ts +13 -0
- package/src/utils/ChatGptCompletionMessageUtil.ts +1 -1
- package/src/utils/ChatGptCompletionStreamingUtil.ts +81 -0
- package/src/utils/__retry.spec.ts +198 -0
- package/src/utils/__retry.ts +18 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const __retry_1 = require("./__retry");
|
|
13
|
+
describe("__get_retry", () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
describe("success cases", () => {
|
|
18
|
+
it("should not retry when successful on first attempt", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
const mockFn = vi.fn().mockResolvedValue("success");
|
|
20
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
21
|
+
const result = yield retryFn(mockFn);
|
|
22
|
+
expect(result).toBe("success");
|
|
23
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(mockFn).toHaveBeenCalledWith(undefined);
|
|
25
|
+
}));
|
|
26
|
+
it("should call exactly 2 times when successful on second attempt", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
const mockFn = vi.fn()
|
|
28
|
+
.mockRejectedValueOnce(new Error("First failure"))
|
|
29
|
+
.mockResolvedValue("success");
|
|
30
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
31
|
+
const result = yield retryFn(mockFn);
|
|
32
|
+
expect(result).toBe("success");
|
|
33
|
+
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
34
|
+
expect(mockFn).toHaveBeenNthCalledWith(1, undefined);
|
|
35
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, new Error("First failure"));
|
|
36
|
+
}));
|
|
37
|
+
it("should call limit times when successful on last attempt", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
const mockFn = vi.fn()
|
|
39
|
+
.mockRejectedValueOnce(new Error("First failure"))
|
|
40
|
+
.mockRejectedValueOnce(new Error("Second failure"))
|
|
41
|
+
.mockResolvedValue("success");
|
|
42
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
43
|
+
const result = yield retryFn(mockFn);
|
|
44
|
+
expect(result).toBe("success");
|
|
45
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
46
|
+
expect(mockFn).toHaveBeenNthCalledWith(1, undefined);
|
|
47
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, new Error("First failure"));
|
|
48
|
+
expect(mockFn).toHaveBeenNthCalledWith(3, new Error("Second failure"));
|
|
49
|
+
}));
|
|
50
|
+
});
|
|
51
|
+
describe("failure cases", () => {
|
|
52
|
+
it("should throw last error after limit attempts", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
const error1 = new Error("First failure");
|
|
54
|
+
const error2 = new Error("Second failure");
|
|
55
|
+
const error3 = new Error("Third failure");
|
|
56
|
+
const mockFn = vi.fn()
|
|
57
|
+
.mockRejectedValueOnce(error1)
|
|
58
|
+
.mockRejectedValueOnce(error2)
|
|
59
|
+
.mockRejectedValueOnce(error3);
|
|
60
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
61
|
+
yield expect(retryFn(mockFn)).rejects.toThrow("Third failure");
|
|
62
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
63
|
+
expect(mockFn).toHaveBeenNthCalledWith(1, undefined);
|
|
64
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, error1);
|
|
65
|
+
expect(mockFn).toHaveBeenNthCalledWith(3, error2);
|
|
66
|
+
}));
|
|
67
|
+
it("should throw error immediately when limit is 1", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
|
+
const error = new Error("Immediate failure");
|
|
69
|
+
const mockFn = vi.fn().mockRejectedValue(error);
|
|
70
|
+
const retryFn = (0, __retry_1.__get_retry)(1);
|
|
71
|
+
yield expect(retryFn(mockFn)).rejects.toThrow("Immediate failure");
|
|
72
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(mockFn).toHaveBeenCalledWith(undefined);
|
|
74
|
+
}));
|
|
75
|
+
});
|
|
76
|
+
describe("prevError propagation", () => {
|
|
77
|
+
it("should pass previous error as prevError correctly", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
|
+
const error1 = new Error("First error");
|
|
79
|
+
const error2 = new Error("Second error");
|
|
80
|
+
const mockFn = vi.fn()
|
|
81
|
+
.mockRejectedValueOnce(error1)
|
|
82
|
+
.mockRejectedValueOnce(error2)
|
|
83
|
+
.mockResolvedValue("success");
|
|
84
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
85
|
+
const result = yield retryFn(mockFn);
|
|
86
|
+
expect(result).toBe("success");
|
|
87
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
88
|
+
expect(mockFn).toHaveBeenNthCalledWith(1, undefined);
|
|
89
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, error1);
|
|
90
|
+
expect(mockFn).toHaveBeenNthCalledWith(3, error2);
|
|
91
|
+
}));
|
|
92
|
+
it("should use initial prevError in first call when provided", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
|
+
const initialError = new Error("Initial error");
|
|
94
|
+
const mockFn = vi.fn().mockResolvedValue("success");
|
|
95
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
96
|
+
const result = yield retryFn(mockFn, initialError);
|
|
97
|
+
expect(result).toBe("success");
|
|
98
|
+
expect(mockFn).toHaveBeenCalledTimes(1);
|
|
99
|
+
expect(mockFn).toHaveBeenCalledWith(initialError);
|
|
100
|
+
}));
|
|
101
|
+
});
|
|
102
|
+
describe("different error types", () => {
|
|
103
|
+
it("should handle string errors correctly", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
|
+
const mockFn = vi.fn()
|
|
105
|
+
.mockRejectedValueOnce("String error")
|
|
106
|
+
.mockResolvedValue("success");
|
|
107
|
+
const retryFn = (0, __retry_1.__get_retry)(2);
|
|
108
|
+
const result = yield retryFn(mockFn);
|
|
109
|
+
expect(result).toBe("success");
|
|
110
|
+
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
111
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, "String error");
|
|
112
|
+
}));
|
|
113
|
+
it("should handle null errors correctly", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
+
const mockFn = vi.fn()
|
|
115
|
+
.mockRejectedValueOnce(null)
|
|
116
|
+
.mockResolvedValue("success");
|
|
117
|
+
const retryFn = (0, __retry_1.__get_retry)(2);
|
|
118
|
+
const result = yield retryFn(mockFn);
|
|
119
|
+
expect(result).toBe("success");
|
|
120
|
+
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
121
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, null);
|
|
122
|
+
}));
|
|
123
|
+
it("should handle undefined errors correctly", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
|
+
const mockFn = vi.fn()
|
|
125
|
+
.mockRejectedValueOnce(undefined)
|
|
126
|
+
.mockResolvedValue("success");
|
|
127
|
+
const retryFn = (0, __retry_1.__get_retry)(2);
|
|
128
|
+
const result = yield retryFn(mockFn);
|
|
129
|
+
expect(result).toBe("success");
|
|
130
|
+
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
131
|
+
expect(mockFn).toHaveBeenNthCalledWith(2, undefined);
|
|
132
|
+
}));
|
|
133
|
+
});
|
|
134
|
+
describe("recursive call verification", () => {
|
|
135
|
+
it("should occur recursive calls in correct order", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
const callOrder = [];
|
|
137
|
+
const mockFn = vi.fn()
|
|
138
|
+
.mockImplementationOnce(() => {
|
|
139
|
+
callOrder.push("first call");
|
|
140
|
+
throw new Error("First failure");
|
|
141
|
+
})
|
|
142
|
+
.mockImplementationOnce(() => {
|
|
143
|
+
callOrder.push("second call");
|
|
144
|
+
throw new Error("Second failure");
|
|
145
|
+
})
|
|
146
|
+
.mockImplementationOnce(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
147
|
+
callOrder.push("third call");
|
|
148
|
+
return Promise.resolve("success");
|
|
149
|
+
}));
|
|
150
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
151
|
+
const result = yield retryFn(mockFn);
|
|
152
|
+
expect(result).toBe("success");
|
|
153
|
+
expect(callOrder).toEqual(["first call", "second call", "third call"]);
|
|
154
|
+
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
155
|
+
}));
|
|
156
|
+
});
|
|
157
|
+
describe("type safety", () => {
|
|
158
|
+
it("should handle different return types correctly", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
159
|
+
const stringFn = vi.fn().mockResolvedValue("string result");
|
|
160
|
+
const numberFn = vi.fn().mockResolvedValue(42);
|
|
161
|
+
const objectFn = vi.fn().mockResolvedValue({ key: "value" });
|
|
162
|
+
const retryFn = (0, __retry_1.__get_retry)(3);
|
|
163
|
+
const stringResult = yield retryFn(stringFn);
|
|
164
|
+
const numberResult = yield retryFn(numberFn);
|
|
165
|
+
const objectResult = yield retryFn(objectFn);
|
|
166
|
+
expect(stringResult).toBe("string result");
|
|
167
|
+
expect(numberResult).toBe(42);
|
|
168
|
+
expect(objectResult).toEqual({ key: "value" });
|
|
169
|
+
}));
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
//# sourceMappingURL=__retry.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"__retry.spec.js","sourceRoot":"","sources":["../../src/utils/__retry.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/orchestrate/call.ts
CHANGED
|
@@ -23,9 +23,11 @@ import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
|
|
|
23
23
|
import { isAgenticaContext } from "../context/internal/isAgenticaContext";
|
|
24
24
|
import { createAssistantMessageEvent, createCallEvent, createExecuteEvent, createJsonParseErrorEvent, createValidateEvent } from "../factory/events";
|
|
25
25
|
import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
|
|
26
|
-
import {
|
|
26
|
+
import { __get_retry } from "../utils/__retry";
|
|
27
|
+
import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
|
|
27
28
|
import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
|
|
28
|
-
import {
|
|
29
|
+
import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
|
|
30
|
+
import { StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
|
|
29
31
|
|
|
30
32
|
import { cancelFunctionFromContext } from "./internal/cancelFunctionFromContext";
|
|
31
33
|
|
|
@@ -33,131 +35,103 @@ export async function call<Model extends ILlmSchema.Model>(
|
|
|
33
35
|
ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
|
|
34
36
|
operations: AgenticaOperation<Model>[],
|
|
35
37
|
): Promise<AgenticaExecuteEvent<Model>[]> {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// USER INPUT
|
|
46
|
-
{
|
|
47
|
-
role: "user",
|
|
48
|
-
content: ctx.prompt.contents.map(decodeUserMessageContent),
|
|
49
|
-
},
|
|
50
|
-
// SYSTEM PROMPT
|
|
51
|
-
...(ctx.config?.systemPrompt?.execute === null
|
|
52
|
-
? []
|
|
53
|
-
: [{
|
|
54
|
-
role: "system",
|
|
55
|
-
content: ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory<Model>[])
|
|
56
|
-
?? AgenticaSystemPrompt.EXECUTE,
|
|
57
|
-
} satisfies OpenAI.ChatCompletionSystemMessageParam]),
|
|
58
|
-
],
|
|
59
|
-
// STACKED FUNCTIONS
|
|
60
|
-
tools: operations.map(
|
|
61
|
-
s =>
|
|
62
|
-
({
|
|
63
|
-
type: "function",
|
|
64
|
-
function: {
|
|
65
|
-
name: s.name,
|
|
66
|
-
|
|
67
|
-
description: s.function.description,
|
|
68
|
-
parameters: (
|
|
69
|
-
(
|
|
70
|
-
"separated" in s.function
|
|
71
|
-
&& s.function.separated !== undefined
|
|
72
|
-
)
|
|
73
|
-
? (s.function.separated.llm
|
|
74
|
-
?? ({
|
|
75
|
-
type: "object",
|
|
76
|
-
properties: {},
|
|
77
|
-
required: [],
|
|
78
|
-
additionalProperties: false,
|
|
79
|
-
$defs: {},
|
|
80
|
-
} satisfies IChatGptSchema.IParameters))
|
|
81
|
-
|
|
82
|
-
: s.function.parameters) as Record<string, any>,
|
|
83
|
-
},
|
|
84
|
-
}) as OpenAI.ChatCompletionTool,
|
|
85
|
-
),
|
|
86
|
-
tool_choice: "auto",
|
|
87
|
-
// parallel_tool_calls: false,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const selectContext: ({
|
|
91
|
-
content: string;
|
|
92
|
-
mpsc: MPSC<string>;
|
|
93
|
-
})[] = [];
|
|
94
|
-
const nullableCompletion = await StreamUtil.reduce<OpenAI.ChatCompletionChunk, Promise<OpenAI.ChatCompletion>>(stream, async (accPromise, chunk) => {
|
|
95
|
-
const acc = await accPromise;
|
|
96
|
-
|
|
97
|
-
const registerContext = (
|
|
98
|
-
choices: OpenAI.ChatCompletionChunk.Choice[],
|
|
99
|
-
) => {
|
|
100
|
-
for (const choice of choices) {
|
|
101
|
-
/**
|
|
102
|
-
* @TODO fix it
|
|
103
|
-
* Sometimes, the complete message arrives along with a finish reason.
|
|
104
|
-
*/
|
|
105
|
-
if (choice.finish_reason != null) {
|
|
106
|
-
selectContext[choice.index]?.mpsc.close();
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
38
|
+
const _retryFn = __get_retry(ctx.config?.retry ?? AgenticaConstant.RETRY);
|
|
39
|
+
const retryFn = async (fn: (prevError?: unknown) => Promise<OpenAI.ChatCompletion>) => {
|
|
40
|
+
return _retryFn(fn).catch((e) => {
|
|
41
|
+
if (e instanceof AssistantMessageEmptyError) {
|
|
42
|
+
return Symbol("emptyAssistantMessage");
|
|
43
|
+
}
|
|
44
|
+
throw e;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
109
47
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
48
|
+
const completion = await retryFn(async (prevError) => {
|
|
49
|
+
const stream: ReadableStream<OpenAI.ChatCompletionChunk> = await ctx.request("call", {
|
|
50
|
+
messages: [
|
|
51
|
+
// COMMON SYSTEM PROMPT
|
|
52
|
+
{
|
|
53
|
+
role: "system",
|
|
54
|
+
content: AgenticaDefaultPrompt.write(ctx.config),
|
|
55
|
+
} satisfies OpenAI.ChatCompletionSystemMessageParam,
|
|
56
|
+
// PREVIOUS HISTORIES
|
|
57
|
+
...ctx.histories.map(decodeHistory).flat(),
|
|
58
|
+
// USER INPUT
|
|
59
|
+
{
|
|
60
|
+
role: "user",
|
|
61
|
+
content: ctx.prompt.contents.map(decodeUserMessageContent),
|
|
62
|
+
},
|
|
63
|
+
...(prevError instanceof AssistantMessageEmptyWithReasoningError ? [
|
|
64
|
+
{
|
|
65
|
+
role: "assistant",
|
|
66
|
+
content: prevError.reasoning,
|
|
67
|
+
} satisfies OpenAI.ChatCompletionMessageParam,
|
|
68
|
+
] : []),
|
|
69
|
+
// SYSTEM PROMPT
|
|
70
|
+
...(ctx.config?.systemPrompt?.execute === null
|
|
71
|
+
? []
|
|
72
|
+
: [{
|
|
73
|
+
role: "system",
|
|
74
|
+
content: ctx.config?.systemPrompt?.execute?.(ctx.histories as MicroAgenticaHistory<Model>[])
|
|
75
|
+
?? AgenticaSystemPrompt.EXECUTE,
|
|
76
|
+
} satisfies OpenAI.ChatCompletionSystemMessageParam]),
|
|
77
|
+
],
|
|
78
|
+
// STACKED FUNCTIONS
|
|
79
|
+
tools: operations.map(
|
|
80
|
+
s =>
|
|
81
|
+
({
|
|
82
|
+
type: "function",
|
|
83
|
+
function: {
|
|
84
|
+
name: s.name,
|
|
113
85
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
86
|
+
description: s.function.description,
|
|
87
|
+
parameters: (
|
|
88
|
+
(
|
|
89
|
+
"separated" in s.function
|
|
90
|
+
&& s.function.separated !== undefined
|
|
91
|
+
)
|
|
92
|
+
? (s.function.separated.llm
|
|
93
|
+
?? ({
|
|
94
|
+
type: "object",
|
|
95
|
+
properties: {},
|
|
96
|
+
required: [],
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
$defs: {},
|
|
99
|
+
} satisfies IChatGptSchema.IParameters))
|
|
119
100
|
|
|
120
|
-
|
|
101
|
+
: s.function.parameters) as Record<string, any>,
|
|
102
|
+
},
|
|
103
|
+
}) as OpenAI.ChatCompletionTool,
|
|
104
|
+
),
|
|
105
|
+
tool_choice: "auto",
|
|
106
|
+
// parallel_tool_calls: false,
|
|
107
|
+
});
|
|
121
108
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
mpsc.produce(choice.delta.content);
|
|
109
|
+
const completion = await reduceStreamingWithDispatch(stream, (props) => {
|
|
110
|
+
const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent(props);
|
|
111
|
+
ctx.dispatch(event);
|
|
112
|
+
});
|
|
127
113
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
await mpsc.waitClosed();
|
|
134
|
-
return selectContext[choice.index]!.content;
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
ctx.dispatch(event);
|
|
114
|
+
const allAssistantMessagesEmpty = completion.choices.every(v => v.message.tool_calls == null && v.message.content === "");
|
|
115
|
+
if (allAssistantMessagesEmpty) {
|
|
116
|
+
const firstChoice = completion.choices.at(0);
|
|
117
|
+
if ((firstChoice?.message as { reasoning?: string })?.reasoning != null) {
|
|
118
|
+
throw new AssistantMessageEmptyWithReasoningError((firstChoice?.message as { reasoning?: string })?.reasoning ?? "");
|
|
138
119
|
}
|
|
139
|
-
|
|
140
|
-
if (acc.object === "chat.completion.chunk") {
|
|
141
|
-
registerContext([acc, chunk].flatMap(v => v.choices));
|
|
142
|
-
return ChatGptCompletionMessageUtil.merge([acc, chunk]);
|
|
120
|
+
throw new AssistantMessageEmptyError();
|
|
143
121
|
}
|
|
144
|
-
|
|
145
|
-
return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
|
|
122
|
+
return completion;
|
|
146
123
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if(emptyAssistantMessages.length > 0) {
|
|
150
|
-
emptyAssistantMessages.forEach(v => {
|
|
124
|
+
|
|
125
|
+
if (typeof completion === "symbol") {
|
|
151
126
|
const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
|
|
152
|
-
stream: toAsyncGenerator(
|
|
127
|
+
stream: toAsyncGenerator(""),
|
|
153
128
|
done: () => true,
|
|
154
|
-
get: () =>
|
|
129
|
+
get: () => "",
|
|
155
130
|
join: async () => {
|
|
156
|
-
return
|
|
131
|
+
return "";
|
|
157
132
|
},
|
|
158
|
-
});
|
|
159
|
-
ctx.dispatch(event);
|
|
160
133
|
});
|
|
134
|
+
ctx.dispatch(event);
|
|
161
135
|
return [];
|
|
162
136
|
}
|
|
163
137
|
|
|
@@ -10,9 +10,7 @@ import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
|
|
|
10
10
|
import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
|
|
11
11
|
import { createDescribeEvent } from "../factory/events";
|
|
12
12
|
import { decodeHistory } from "../factory/histories";
|
|
13
|
-
import {
|
|
14
|
-
import { MPSC } from "../utils/MPSC";
|
|
15
|
-
import { streamDefaultReaderToAsyncGenerator, StreamUtil } from "../utils/StreamUtil";
|
|
13
|
+
import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
|
|
16
14
|
|
|
17
15
|
export async function describe<Model extends ILlmSchema.Model>(
|
|
18
16
|
ctx: AgenticaContext<Model> | MicroAgenticaContext<Model>,
|
|
@@ -41,68 +39,12 @@ export async function describe<Model extends ILlmSchema.Model>(
|
|
|
41
39
|
],
|
|
42
40
|
});
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
OpenAI.ChatCompletionChunk,
|
|
51
|
-
Promise<OpenAI.ChatCompletion>
|
|
52
|
-
>(completionStream, async (accPromise, chunk) => {
|
|
53
|
-
const acc = await accPromise;
|
|
54
|
-
const registerContext = (
|
|
55
|
-
choices: OpenAI.ChatCompletionChunk.Choice[],
|
|
56
|
-
) => {
|
|
57
|
-
for (const choice of choices) {
|
|
58
|
-
/**
|
|
59
|
-
* @TODO fix it
|
|
60
|
-
* Sometimes, the complete message arrives along with a finish reason.
|
|
61
|
-
*/
|
|
62
|
-
if (choice.finish_reason != null) {
|
|
63
|
-
describeContext[choice.index]!.mpsc.close();
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (choice.delta.content == null) {
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (describeContext[choice.index] != null) {
|
|
72
|
-
describeContext[choice.index]!.content += choice.delta.content;
|
|
73
|
-
describeContext[choice.index]!.mpsc.produce(choice.delta.content);
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const mpsc = new MPSC<string>();
|
|
78
|
-
|
|
79
|
-
describeContext[choice.index] = {
|
|
80
|
-
content: choice.delta.content,
|
|
81
|
-
mpsc,
|
|
82
|
-
};
|
|
83
|
-
mpsc.produce(choice.delta.content);
|
|
84
|
-
|
|
85
|
-
const event: AgenticaDescribeEvent<Model> = createDescribeEvent({
|
|
86
|
-
executes: histories,
|
|
87
|
-
stream: streamDefaultReaderToAsyncGenerator(mpsc.consumer.getReader()),
|
|
88
|
-
done: () => mpsc.done(),
|
|
89
|
-
get: () => describeContext[choice.index]?.content ?? "",
|
|
90
|
-
join: async () => {
|
|
91
|
-
await mpsc.waitClosed();
|
|
92
|
-
return describeContext[choice.index]!.content;
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
ctx.dispatch(event);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
if (acc.object === "chat.completion.chunk") {
|
|
100
|
-
registerContext([acc, chunk].flatMap(v => v.choices));
|
|
101
|
-
return ChatGptCompletionMessageUtil.merge([acc, chunk]);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
registerContext(chunk.choices);
|
|
105
|
-
return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
|
|
42
|
+
await reduceStreamingWithDispatch(completionStream, (props) => {
|
|
43
|
+
const event: AgenticaDescribeEvent<Model> = createDescribeEvent({
|
|
44
|
+
executes: histories,
|
|
45
|
+
...props,
|
|
46
|
+
});
|
|
47
|
+
ctx.dispatch(event);
|
|
106
48
|
});
|
|
107
49
|
}
|
|
108
50
|
|
|
@@ -11,9 +11,7 @@ import { AgenticaDefaultPrompt } from "../constants/AgenticaDefaultPrompt";
|
|
|
11
11
|
import { AgenticaSystemPrompt } from "../constants/AgenticaSystemPrompt";
|
|
12
12
|
import { createAssistantMessageEvent } from "../factory/events";
|
|
13
13
|
import { decodeHistory, decodeUserMessageContent } from "../factory/histories";
|
|
14
|
-
import {
|
|
15
|
-
import { MPSC } from "../utils/MPSC";
|
|
16
|
-
import { streamDefaultReaderToAsyncGenerator, StreamUtil } from "../utils/StreamUtil";
|
|
14
|
+
import { reduceStreamingWithDispatch } from "../utils/ChatGptCompletionStreamingUtil";
|
|
17
15
|
|
|
18
16
|
const FUNCTION: ILlmFunction<"chatgpt"> = typia.llm.application<
|
|
19
17
|
__IChatInitialApplication,
|
|
@@ -65,67 +63,9 @@ export async function initialize<Model extends ILlmSchema.Model>(ctx: AgenticaCo
|
|
|
65
63
|
// parallel_tool_calls: false,
|
|
66
64
|
});
|
|
67
65
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
})[] = [];
|
|
72
|
-
|
|
73
|
-
const completion = await StreamUtil.reduce<
|
|
74
|
-
OpenAI.ChatCompletionChunk,
|
|
75
|
-
Promise<OpenAI.ChatCompletion>
|
|
76
|
-
>(completionStream, async (accPromise, chunk) => {
|
|
77
|
-
const acc = await accPromise;
|
|
78
|
-
const registerContext = (
|
|
79
|
-
choices: OpenAI.ChatCompletionChunk.Choice[],
|
|
80
|
-
) => {
|
|
81
|
-
for (const choice of choices) {
|
|
82
|
-
/**
|
|
83
|
-
* @TODO fix it
|
|
84
|
-
* Sometimes, the complete message arrives along with a finish reason.
|
|
85
|
-
*/
|
|
86
|
-
if (choice.finish_reason != null) {
|
|
87
|
-
textContext[choice.index]?.mpsc.close();
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (choice.delta.content == null || choice.delta.content.length === 0) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (textContext[choice.index] != null) {
|
|
96
|
-
textContext[choice.index]!.content += choice.delta.content;
|
|
97
|
-
textContext[choice.index]!.mpsc.produce(choice.delta.content);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const mpsc = new MPSC<string>();
|
|
102
|
-
|
|
103
|
-
textContext[choice.index] = {
|
|
104
|
-
content: choice.delta.content,
|
|
105
|
-
mpsc,
|
|
106
|
-
};
|
|
107
|
-
mpsc.produce(choice.delta.content);
|
|
108
|
-
|
|
109
|
-
const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
|
|
110
|
-
stream: streamDefaultReaderToAsyncGenerator(mpsc.consumer.getReader()),
|
|
111
|
-
done: () => mpsc.done(),
|
|
112
|
-
get: () => textContext[choice.index]!.content,
|
|
113
|
-
join: async () => {
|
|
114
|
-
await mpsc.waitClosed();
|
|
115
|
-
return textContext[choice.index]!.content;
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
ctx.dispatch(event);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
if (acc.object === "chat.completion.chunk") {
|
|
123
|
-
registerContext([acc, chunk].flatMap(v => v.choices));
|
|
124
|
-
return ChatGptCompletionMessageUtil.merge([acc, chunk]);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
registerContext(chunk.choices);
|
|
128
|
-
return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
|
|
66
|
+
const completion = await reduceStreamingWithDispatch(completionStream, (props) => {
|
|
67
|
+
const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent(props);
|
|
68
|
+
ctx.dispatch(event);
|
|
129
69
|
});
|
|
130
70
|
|
|
131
71
|
if (completion === null) {
|