@agentica/core 0.32.1 → 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.
Files changed (34) hide show
  1. package/lib/index.mjs +308 -334
  2. package/lib/index.mjs.map +1 -1
  3. package/lib/orchestrate/call.js +87 -107
  4. package/lib/orchestrate/call.js.map +1 -1
  5. package/lib/orchestrate/describe.js +5 -50
  6. package/lib/orchestrate/describe.js.map +1 -1
  7. package/lib/orchestrate/initialize.js +5 -50
  8. package/lib/orchestrate/initialize.js.map +1 -1
  9. package/lib/orchestrate/select.js +107 -126
  10. package/lib/orchestrate/select.js.map +1 -1
  11. package/lib/utils/AssistantMessageEmptyError.d.ts +7 -0
  12. package/lib/utils/AssistantMessageEmptyError.js +17 -0
  13. package/lib/utils/AssistantMessageEmptyError.js.map +1 -0
  14. package/lib/utils/ChatGptCompletionMessageUtil.js +15 -8
  15. package/lib/utils/ChatGptCompletionMessageUtil.js.map +1 -1
  16. package/lib/utils/ChatGptCompletionStreamingUtil.d.ts +8 -0
  17. package/lib/utils/ChatGptCompletionStreamingUtil.js +74 -0
  18. package/lib/utils/ChatGptCompletionStreamingUtil.js.map +1 -0
  19. package/lib/utils/__retry.d.ts +1 -0
  20. package/lib/utils/__retry.js +30 -0
  21. package/lib/utils/__retry.js.map +1 -0
  22. package/lib/utils/__retry.spec.d.ts +1 -0
  23. package/lib/utils/__retry.spec.js +172 -0
  24. package/lib/utils/__retry.spec.js.map +1 -0
  25. package/package.json +1 -1
  26. package/src/orchestrate/call.ts +88 -114
  27. package/src/orchestrate/describe.ts +7 -65
  28. package/src/orchestrate/initialize.ts +4 -64
  29. package/src/orchestrate/select.ts +111 -138
  30. package/src/utils/AssistantMessageEmptyError.ts +13 -0
  31. package/src/utils/ChatGptCompletionMessageUtil.ts +14 -0
  32. package/src/utils/ChatGptCompletionStreamingUtil.ts +81 -0
  33. package/src/utils/__retry.spec.ts +198 -0
  34. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentica/core",
3
- "version": "0.32.1",
3
+ "version": "0.32.3-dev.1",
4
4
  "description": "Agentic AI Library specialized in LLM Function Calling",
5
5
  "author": "Wrtn Technologies",
6
6
  "license": "MIT",
@@ -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 { MPSC } from "../utils";
26
+ import { __get_retry } from "../utils/__retry";
27
+ import { AssistantMessageEmptyError, AssistantMessageEmptyWithReasoningError } from "../utils/AssistantMessageEmptyError";
27
28
  import { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
28
- import { streamDefaultReaderToAsyncGenerator, StreamUtil, toAsyncGenerator } from "../utils/StreamUtil";
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 stream: ReadableStream<OpenAI.ChatCompletionChunk> = await ctx.request("call", {
37
- messages: [
38
- // COMMON SYSTEM PROMPT
39
- {
40
- role: "system",
41
- content: AgenticaDefaultPrompt.write(ctx.config),
42
- } satisfies OpenAI.ChatCompletionSystemMessageParam,
43
- // PREVIOUS HISTORIES
44
- ...ctx.histories.map(decodeHistory).flat(),
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
- if (choice.delta.content == null || choice.delta.content === "") {
111
- continue;
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
- if (selectContext[choice.index] != null) {
115
- selectContext[choice.index]!.content += choice.delta.content;
116
- selectContext[choice.index]!.mpsc.produce(choice.delta.content);
117
- continue;
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
- const mpsc = new MPSC<string>();
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
- selectContext[choice.index] = {
123
- content: choice.delta.content,
124
- mpsc,
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
- const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
129
- stream: streamDefaultReaderToAsyncGenerator(mpsc.consumer.getReader()),
130
- done: () => mpsc.done(),
131
- get: () => selectContext[choice.index]?.content ?? "",
132
- join: async () => {
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
- registerContext(chunk.choices);
145
- return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
122
+ return completion;
146
123
  });
147
- const completion = nullableCompletion!;
148
- const emptyAssistantMessages = completion.choices.filter(v => v.message.tool_calls == null && v.message.content === "");
149
- if(emptyAssistantMessages.length > 0) {
150
- emptyAssistantMessages.forEach(v => {
124
+
125
+ if (typeof completion === "symbol") {
151
126
  const event: AgenticaAssistantMessageEvent = createAssistantMessageEvent({
152
- stream: toAsyncGenerator(v.message.content ?? ""),
127
+ stream: toAsyncGenerator(""),
153
128
  done: () => true,
154
- get: () => v.message.content ?? "",
129
+ get: () => "",
155
130
  join: async () => {
156
- return v.message.content ?? "";
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 { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
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
- const describeContext: ({
45
- content: string;
46
- mpsc: MPSC<string>;
47
- })[] = [];
48
-
49
- await StreamUtil.reduce<
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 { ChatGptCompletionMessageUtil } from "../utils/ChatGptCompletionMessageUtil";
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 textContext: ({
69
- content: string;
70
- mpsc: MPSC<string>;
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) {