@celljs/ai-core 3.4.2 → 3.4.4
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/common/chat/index.d.ts +1 -0
- package/lib/common/chat/index.d.ts.map +1 -1
- package/lib/common/chat/index.js +1 -0
- package/lib/common/chat/index.js.map +1 -1
- package/lib/common/chat/message/message-protocol.d.ts +29 -4
- package/lib/common/chat/message/message-protocol.d.ts.map +1 -1
- package/lib/common/chat/message/message-protocol.js.map +1 -1
- package/lib/common/chat/metadata/chat-generation-metadata.d.ts +2 -2
- package/lib/common/chat/metadata/chat-generation-metadata.d.ts.map +1 -1
- package/lib/common/chat/metadata/chat-generation-metadata.js +2 -3
- package/lib/common/chat/metadata/chat-generation-metadata.js.map +1 -1
- package/lib/common/chat/metadata/metadata-protocol.d.ts +15 -11
- package/lib/common/chat/metadata/metadata-protocol.d.ts.map +1 -1
- package/lib/common/chat/metadata/metadata-protocol.js +26 -41
- package/lib/common/chat/metadata/metadata-protocol.js.map +1 -1
- package/lib/common/chat/model/chat-protocol.d.ts +3 -0
- package/lib/common/chat/model/chat-protocol.d.ts.map +1 -1
- package/lib/common/chat/model/chat-protocol.js +18 -2
- package/lib/common/chat/model/chat-protocol.js.map +1 -1
- package/lib/common/chat/prompt/prompt-protocol.d.ts +1 -1
- package/lib/common/chat/prompt/prompt-protocol.d.ts.map +1 -1
- package/lib/common/chat/prompt/prompt-template.d.ts +2 -1
- package/lib/common/chat/prompt/prompt-template.d.ts.map +1 -1
- package/lib/common/chat/prompt/prompt-template.js +10 -4
- package/lib/common/chat/prompt/prompt-template.js.map +1 -1
- package/lib/common/chat/tool/index.d.ts +3 -0
- package/lib/common/chat/tool/index.d.ts.map +1 -0
- package/lib/common/chat/tool/index.js +6 -0
- package/lib/common/chat/tool/index.js.map +1 -0
- package/lib/common/chat/tool/tool-handler.d.ts +12 -0
- package/lib/common/chat/tool/tool-handler.d.ts.map +1 -0
- package/lib/common/chat/tool/tool-handler.js +54 -0
- package/lib/common/chat/tool/tool-handler.js.map +1 -0
- package/lib/common/chat/tool/tool-protocol.d.ts +8 -0
- package/lib/common/chat/tool/tool-protocol.d.ts.map +1 -0
- package/lib/common/chat/tool/tool-protocol.js +5 -0
- package/lib/common/chat/tool/tool-protocol.js.map +1 -0
- package/lib/common/error/error.d.ts +3 -0
- package/lib/common/error/error.d.ts.map +1 -1
- package/lib/common/error/error.js +7 -1
- package/lib/common/error/error.js.map +1 -1
- package/lib/common/model/function/function-callback-register.d.ts +9 -0
- package/lib/common/model/function/function-callback-register.d.ts.map +1 -0
- package/lib/common/model/function/function-callback-register.js +43 -0
- package/lib/common/model/function/function-callback-register.js.map +1 -0
- package/lib/common/model/function/function-protocol.d.ts +28 -2
- package/lib/common/model/function/function-protocol.d.ts.map +1 -1
- package/lib/common/model/function/function-protocol.js +42 -1
- package/lib/common/model/function/function-protocol.js.map +1 -1
- package/lib/common/model/function/index.d.ts +1 -0
- package/lib/common/model/function/index.d.ts.map +1 -1
- package/lib/common/model/function/index.js +1 -0
- package/lib/common/model/function/index.js.map +1 -1
- package/lib/common/utils/index.d.ts +1 -0
- package/lib/common/utils/index.d.ts.map +1 -1
- package/lib/common/utils/index.js +1 -0
- package/lib/common/utils/index.js.map +1 -1
- package/lib/common/utils/sse-util.d.ts +1 -1
- package/lib/common/utils/sse-util.d.ts.map +1 -1
- package/lib/common/utils/sse-util.js.map +1 -1
- package/lib/common/utils/usage-util.d.ts +17 -0
- package/lib/common/utils/usage-util.d.ts.map +1 -0
- package/lib/common/utils/usage-util.js +62 -0
- package/lib/common/utils/usage-util.js.map +1 -0
- package/package.json +5 -5
- package/src/common/chat/index.ts +1 -0
- package/src/common/chat/message/message-protocol.ts +31 -4
- package/src/common/chat/metadata/chat-generation-metadata.ts +4 -4
- package/src/common/chat/metadata/metadata-protocol.ts +33 -49
- package/src/common/chat/model/chat-protocol.ts +22 -4
- package/src/common/chat/prompt/prompt-protocol.ts +1 -1
- package/src/common/chat/prompt/prompt-template.ts +12 -6
- package/src/common/chat/tool/index.ts +2 -0
- package/src/common/chat/tool/tool-handler.ts +51 -0
- package/src/common/chat/tool/tool-protocol.ts +9 -0
- package/src/common/error/error.ts +6 -0
- package/src/common/model/function/function-callback-register.ts +38 -0
- package/src/common/model/function/function-protocol.ts +59 -2
- package/src/common/model/function/index.ts +1 -0
- package/src/common/utils/index.ts +1 -0
- package/src/common/utils/sse-util.ts +1 -1
- package/src/common/utils/usage-util.ts +60 -0
|
@@ -10,25 +10,29 @@ export interface Usage {
|
|
|
10
10
|
/**
|
|
11
11
|
* The number of tokens used in the prompt of the AI request.
|
|
12
12
|
*/
|
|
13
|
-
readonly promptTokens
|
|
13
|
+
readonly promptTokens?: number;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The number of tokens returned in the generation (aka completion)
|
|
17
17
|
* of the AI's response.
|
|
18
18
|
*/
|
|
19
|
-
readonly generationTokens
|
|
19
|
+
readonly generationTokens?: number;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* The total number of tokens from both the prompt of an AI request
|
|
23
23
|
* and generation of the AI's response.
|
|
24
24
|
*/
|
|
25
|
-
readonly totalTokens
|
|
25
|
+
readonly totalTokens?: number;
|
|
26
26
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export namespace Usage {
|
|
30
|
-
export function
|
|
31
|
-
return { promptTokens, generationTokens, totalTokens:
|
|
30
|
+
export function createEmpty(): Usage {
|
|
31
|
+
return { promptTokens: 0, generationTokens: 0, totalTokens: 0 };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function from(promptTokens = 0, generationTokens = 0, totalTokens = 0): Usage {
|
|
35
|
+
return { promptTokens, generationTokens, totalTokens: totalTokens ? totalTokens : promptTokens + generationTokens };
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
38
|
|
|
@@ -42,37 +46,37 @@ export interface RateLimit {
|
|
|
42
46
|
* The maximum number of requests that are permitted before exhausting the
|
|
43
47
|
* rate limit.
|
|
44
48
|
*/
|
|
45
|
-
readonly requestsLimit
|
|
49
|
+
readonly requestsLimit?: number;
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
* The remaining number of requests that are permitted before exhausting the
|
|
49
53
|
* requestsLimit rate limit.
|
|
50
54
|
*/
|
|
51
|
-
readonly requestsRemaining
|
|
55
|
+
readonly requestsRemaining?: number;
|
|
52
56
|
|
|
53
57
|
/**
|
|
54
58
|
* The duration time until the rate limit (based on requests) resets
|
|
55
59
|
* to its requestsLimit initial state.
|
|
56
60
|
*/
|
|
57
|
-
readonly requestsReset
|
|
61
|
+
readonly requestsReset?: number;
|
|
58
62
|
|
|
59
63
|
/**
|
|
60
64
|
* The maximum number of tokens that are permitted before exhausting the rate
|
|
61
65
|
* limit.
|
|
62
66
|
*/
|
|
63
|
-
readonly tokensLimit
|
|
67
|
+
readonly tokensLimit?: number;
|
|
64
68
|
|
|
65
69
|
/**
|
|
66
70
|
* The remaining number of tokens that are permitted before exhausting the
|
|
67
71
|
* tokensLimit rate limit.
|
|
68
72
|
*/
|
|
69
|
-
readonly tokensRemaining
|
|
73
|
+
readonly tokensRemaining?: number;
|
|
70
74
|
|
|
71
75
|
/**
|
|
72
76
|
* The duration time until the rate limit (based on tokens) resets to
|
|
73
77
|
* its tokensLimit initial state.
|
|
74
78
|
*/
|
|
75
|
-
readonly tokensReset
|
|
79
|
+
readonly tokensReset?: number;
|
|
76
80
|
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -123,6 +127,12 @@ export namespace PromptMetadata {
|
|
|
123
127
|
}
|
|
124
128
|
}
|
|
125
129
|
|
|
130
|
+
export namespace RateLimit {
|
|
131
|
+
export function createEmpty(): RateLimit {
|
|
132
|
+
return { requestsLimit: 0, requestsRemaining: 0, requestsReset: 0, tokensLimit: 0, tokensRemaining: 0, tokensReset: 0 };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
126
136
|
export interface ChatResponseMetadata extends ResponseMetadata {
|
|
127
137
|
id?: string;
|
|
128
138
|
model?: string;
|
|
@@ -144,25 +154,7 @@ export interface ChatResponseMetadata extends ResponseMetadata {
|
|
|
144
154
|
|
|
145
155
|
export class ChatResponseMetadataBuilder {
|
|
146
156
|
|
|
147
|
-
private readonly chatResponseMetadata: ChatResponseMetadata =
|
|
148
|
-
id: '',
|
|
149
|
-
model: '',
|
|
150
|
-
rateLimit: {
|
|
151
|
-
requestsLimit: 0,
|
|
152
|
-
requestsRemaining: 0,
|
|
153
|
-
requestsReset: 0,
|
|
154
|
-
tokensLimit: 0,
|
|
155
|
-
tokensRemaining: 0,
|
|
156
|
-
tokensReset: 0
|
|
157
|
-
},
|
|
158
|
-
usage: {
|
|
159
|
-
promptTokens: 0,
|
|
160
|
-
generationTokens: 0,
|
|
161
|
-
totalTokens: 0
|
|
162
|
-
},
|
|
163
|
-
promptMetadata: [] as PromptMetadata,
|
|
164
|
-
extra: {}
|
|
165
|
-
};
|
|
157
|
+
private readonly chatResponseMetadata: ChatResponseMetadata = ChatResponseMetadata.createEmpty();
|
|
166
158
|
|
|
167
159
|
id(id: string): ChatResponseMetadataBuilder {
|
|
168
160
|
this.chatResponseMetadata.id = id;
|
|
@@ -207,25 +199,17 @@ export class ChatResponseMetadataBuilder {
|
|
|
207
199
|
}
|
|
208
200
|
|
|
209
201
|
export namespace ChatResponseMetadata {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
usage: {
|
|
222
|
-
promptTokens: 0,
|
|
223
|
-
generationTokens: 0,
|
|
224
|
-
totalTokens: 0
|
|
225
|
-
},
|
|
226
|
-
promptMetadata: [] as PromptMetadata,
|
|
227
|
-
extra: {}
|
|
228
|
-
};
|
|
202
|
+
|
|
203
|
+
export function createEmpty(): ChatResponseMetadata {
|
|
204
|
+
return {
|
|
205
|
+
id: '',
|
|
206
|
+
model: '',
|
|
207
|
+
rateLimit: RateLimit.createEmpty(),
|
|
208
|
+
usage: Usage.createEmpty(),
|
|
209
|
+
promptMetadata: [] as PromptMetadata,
|
|
210
|
+
extra: {}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
229
213
|
|
|
230
214
|
export function builder(): ChatResponseMetadataBuilder {
|
|
231
215
|
return new ChatResponseMetadataBuilder();
|
|
@@ -10,23 +10,41 @@ export const ChatModel = Symbol('ChatModel');
|
|
|
10
10
|
* Represents a response returned by the AI.
|
|
11
11
|
*/
|
|
12
12
|
export interface Generation extends ModelResult<AssistantMessage> {
|
|
13
|
-
|
|
13
|
+
metadata: ChatGenerationMetadata;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface ChatResponse extends ModelResponse<Generation> {
|
|
17
|
-
|
|
17
|
+
metadata: ChatResponseMetadata;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export namespace Generation {
|
|
21
|
-
export function from(output: AssistantMessage, metadata = ChatGenerationMetadata.
|
|
21
|
+
export function from(output: AssistantMessage, metadata = ChatGenerationMetadata.from()): Generation {
|
|
22
22
|
return { output, metadata };
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export namespace ChatResponse {
|
|
27
|
-
export function from(results: Generation[], metadata = ChatResponseMetadata.
|
|
27
|
+
export function from(results: Generation[], metadata = ChatResponseMetadata.createEmpty()): ChatResponse {
|
|
28
28
|
return { result: results[0], results, metadata };
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
export function isToolCall(chatResponse: ChatResponse, toolCallFinishReasons: Set<string>): boolean {
|
|
32
|
+
if (!chatResponse) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const generations = chatResponse.results;
|
|
37
|
+
if (!generations || generations.length === 0) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return generations.some(g => doIsToolCall(g, toolCallFinishReasons));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function doIsToolCall(generation: Generation, toolCallFinishReasons: Set<string>): boolean {
|
|
45
|
+
const finishReason = generation.metadata.finishReason ?? '';
|
|
46
|
+
return generation.output.toolCalls?.length > 0 && toolCallFinishReasons.has(finishReason.toLowerCase());
|
|
47
|
+
}
|
|
30
48
|
}
|
|
31
49
|
|
|
32
50
|
export interface StreamingChatModel extends StreamingModel<Prompt, ChatResponse> {
|
|
@@ -30,5 +30,5 @@ export interface PromptTemplateContext {
|
|
|
30
30
|
|
|
31
31
|
export interface PromptTemplate {
|
|
32
32
|
render(template: string, ctx?: PromptTemplateContext): Promise<string>;
|
|
33
|
-
create(template: string, ctx?: PromptTemplateContext): Promise<Prompt>;
|
|
33
|
+
create(template: string | Message[], ctx?: PromptTemplateContext): Promise<Prompt>;
|
|
34
34
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Autowired, Component, ExpressionHandler, IllegalArgumentError } from '@celljs/core';
|
|
2
2
|
import { Prompt, PromptTemplate, PromptTemplateContext } from './prompt-protocol';
|
|
3
3
|
import { PromptImpl } from './prompt';
|
|
4
|
-
import { MessageType, SystemMessage } from '../message';
|
|
4
|
+
import { Message, MessageType, SystemMessage } from '../message';
|
|
5
5
|
|
|
6
6
|
@Component(PromptTemplate)
|
|
7
7
|
export class PromptTemplateImpl implements PromptTemplate {
|
|
@@ -15,11 +15,17 @@ export class PromptTemplateImpl implements PromptTemplate {
|
|
|
15
15
|
}
|
|
16
16
|
return template;
|
|
17
17
|
}
|
|
18
|
-
async create(template: string, ctx?: PromptTemplateContext): Promise<Prompt> {
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return new PromptImpl(
|
|
18
|
+
async create(template: string | Message[], ctx?: PromptTemplateContext): Promise<Prompt> {
|
|
19
|
+
if (Array.isArray(template)
|
|
20
|
+
&& template.some(message => Message.isMessage(message))
|
|
21
|
+
) {
|
|
22
|
+
return new PromptImpl(template, ctx?.chatOptions);
|
|
23
|
+
} else if (typeof template === 'string') {
|
|
24
|
+
if (!ctx?.messageType || ctx?.messageType === MessageType.USER) {
|
|
25
|
+
return new PromptImpl(await this.render(template, ctx), ctx?.chatOptions);
|
|
26
|
+
} else if (ctx?.messageType === MessageType.SYSTEM) {
|
|
27
|
+
return new PromptImpl(new SystemMessage(await this.render(template, ctx)), ctx?.chatOptions);
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
30
|
throw new IllegalArgumentError(`Invalid message type: ${ctx?.messageType}`);
|
|
25
31
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Autowired, Component, IllegalStateError } from '@celljs/core';
|
|
2
|
+
import { FunctionCallbackRegister, FunctionCallingOptions, ToolContext } from '../../model';
|
|
3
|
+
import { ChatResponse } from '../model';
|
|
4
|
+
import { Prompt } from '../prompt';
|
|
5
|
+
import { ToolHandler } from './tool-protocol';
|
|
6
|
+
import { AssistantMessage, Message, ToolResponse, ToolResponseMessage } from '../message';
|
|
7
|
+
|
|
8
|
+
@Component(ToolHandler)
|
|
9
|
+
export class ToolHanderImpl implements ToolHandler {
|
|
10
|
+
|
|
11
|
+
@Autowired(FunctionCallbackRegister)
|
|
12
|
+
protected readonly functionCallbackRegister: FunctionCallbackRegister;
|
|
13
|
+
|
|
14
|
+
protected async executeFunctions(assistantMessage: AssistantMessage, toolContext: ToolContext): Promise<ToolResponseMessage> {
|
|
15
|
+
const toolResponses: ToolResponse[] = [];
|
|
16
|
+
for (const toolCall of assistantMessage.toolCalls) {
|
|
17
|
+
const functionResponse = await this.functionCallbackRegister.call(toolCall.name, toolCall.arguments, toolContext);
|
|
18
|
+
toolResponses.push({
|
|
19
|
+
id: toolCall.id,
|
|
20
|
+
name: toolCall.name,
|
|
21
|
+
responseData: functionResponse
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return new ToolResponseMessage(toolResponses);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected buildToolCallConversation(previousMessages: Message[], assistantMessage: AssistantMessage, toolResponseMessage: ToolResponseMessage): Message[] {
|
|
28
|
+
const messages = [...previousMessages];
|
|
29
|
+
messages.push(assistantMessage);
|
|
30
|
+
messages.push(toolResponseMessage);
|
|
31
|
+
return messages;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async handle(prompt: Prompt, chatResponse: ChatResponse): Promise<Message[]> {
|
|
35
|
+
const toolCallGeneration = chatResponse.results.find(result => result.output.toolCalls?.length > 0);
|
|
36
|
+
if (!toolCallGeneration) {
|
|
37
|
+
throw new IllegalStateError('No tool call generation found in the response!');
|
|
38
|
+
}
|
|
39
|
+
const assistantMessage = toolCallGeneration.output;
|
|
40
|
+
let toolContext: ToolContext = {};
|
|
41
|
+
const options = prompt.options;
|
|
42
|
+
if (FunctionCallingOptions.is(options) && options.toolContext) {
|
|
43
|
+
toolContext = { ...options.toolContext };
|
|
44
|
+
const toolCallHistory = prompt.copy().instructions;
|
|
45
|
+
toolContext[ToolContext.TOOL_CALL_HISTORY] = toolCallHistory;
|
|
46
|
+
}
|
|
47
|
+
const toolResponseMessage = await this.executeFunctions(assistantMessage, toolContext);
|
|
48
|
+
const toolConversationHistory = this.buildToolCallConversation(prompt.instructions, assistantMessage, toolResponseMessage);
|
|
49
|
+
return toolConversationHistory;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Message } from '../message';
|
|
2
|
+
import { ChatResponse } from '../model';
|
|
3
|
+
import { Prompt } from '../prompt';
|
|
4
|
+
|
|
5
|
+
export const ToolHandler = Symbol('ToolHandler');
|
|
6
|
+
|
|
7
|
+
export interface ToolHandler {
|
|
8
|
+
handle(prompt: Prompt, chatResponse: ChatResponse): Promise<Message[]>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Component } from '@celljs/core';
|
|
2
|
+
import { FunctionCallback, FunctionCallbackRegister, ToolContext } from './function-protocol';
|
|
3
|
+
import { NotFoundError } from '../../error';
|
|
4
|
+
|
|
5
|
+
@Component(FunctionCallbackRegister)
|
|
6
|
+
export class FunctionCallbackRegisterImpl implements FunctionCallbackRegister {
|
|
7
|
+
|
|
8
|
+
private functionCallbacks: Map<string, FunctionCallback> = new Map<string, FunctionCallback>();
|
|
9
|
+
|
|
10
|
+
register(functionCallback: FunctionCallback): void {
|
|
11
|
+
this.functionCallbacks.set(functionCallback.name, functionCallback);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
unregister(functionName: string): void {
|
|
15
|
+
this.functionCallbacks.delete(functionName);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
call(functionName: string, functionArguments: string, toolContext: ToolContext): Promise<string> {
|
|
19
|
+
const functionCallback = this.functionCallbacks.get(functionName);
|
|
20
|
+
if (functionCallback) {
|
|
21
|
+
return functionCallback.call(functionArguments, toolContext);
|
|
22
|
+
}
|
|
23
|
+
throw new NotFoundError(`Function ${functionName} not found`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resolve(functionNames: string[]): FunctionCallback[] {
|
|
27
|
+
const functionCallbacks: FunctionCallback[] = [];
|
|
28
|
+
new Set(functionNames).forEach(functionName => {
|
|
29
|
+
const functionCallback = this.functionCallbacks.get(functionName);
|
|
30
|
+
if (functionCallback) {
|
|
31
|
+
functionCallbacks.push(functionCallback);
|
|
32
|
+
} else {
|
|
33
|
+
throw new NotFoundError(`No function callback found for name: ${functionName}`);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return functionCallbacks;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { ChatOptions } from '../../chat/prompt';
|
|
2
2
|
|
|
3
|
+
export const FunctionCallbackRegister = Symbol('FunctionCallbackRegister');
|
|
4
|
+
|
|
5
|
+
export interface ToolContext extends Record<string, any> {}
|
|
6
|
+
|
|
7
|
+
export namespace ToolContext {
|
|
8
|
+
export const TOOL_CALL_HISTORY = 'TOOL_CALL_HISTORY';
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
/**
|
|
4
12
|
* Represents a model function call handler. Implementations are registered with the
|
|
5
13
|
* Models and called on prompts that trigger the function call.
|
|
@@ -28,9 +36,10 @@ export interface FunctionCallback {
|
|
|
28
36
|
* @param functionArguments JSON string with the function arguments to be passed to the
|
|
29
37
|
* function. The arguments are defined as JSON schema usually registered with the the
|
|
30
38
|
* model.
|
|
39
|
+
* @param toolContext Optional tool context to be passed to the function call.
|
|
31
40
|
* @return String containing the function call response.
|
|
32
41
|
*/
|
|
33
|
-
call(functionArguments: string): Promise<string>;
|
|
42
|
+
call(functionArguments: string, toolContext?: ToolContext): Promise<string>;
|
|
34
43
|
|
|
35
44
|
}
|
|
36
45
|
|
|
@@ -49,13 +58,61 @@ export interface FunctionCallingOptions {
|
|
|
49
58
|
* List of function names from the ChatClient registry to be used in the next
|
|
50
59
|
* chat completion requests.
|
|
51
60
|
*/
|
|
52
|
-
functions: Set<
|
|
61
|
+
functions: Set<string>;
|
|
62
|
+
|
|
63
|
+
proxyToolCalls?: boolean;
|
|
64
|
+
|
|
65
|
+
toolContext?: ToolContext;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
export namespace FunctionCallingOptions {
|
|
56
69
|
export function is(obj: any): obj is FunctionCallingOptions {
|
|
57
70
|
return obj && obj.functionCallbacks !== undefined && obj.functions !== undefined;
|
|
58
71
|
}
|
|
72
|
+
|
|
73
|
+
export function getEnabledFunctionsToCall(runtimeFunctionOptions: FunctionCallingOptions): Set<string> {
|
|
74
|
+
const enabledFunctionsToCall = new Set<string>();
|
|
75
|
+
if (runtimeFunctionOptions) {
|
|
76
|
+
// Add the explicitly enabled functions.
|
|
77
|
+
if (runtimeFunctionOptions.functions) {
|
|
78
|
+
runtimeFunctionOptions.functions.forEach(fn => {
|
|
79
|
+
enabledFunctionsToCall.add(fn);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (runtimeFunctionOptions.functionCallbacks) {
|
|
84
|
+
runtimeFunctionOptions.functionCallbacks.forEach(functionCallback => {
|
|
85
|
+
// Automatically enable the function, usually from prompt callback.
|
|
86
|
+
enabledFunctionsToCall.add(functionCallback.name);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return enabledFunctionsToCall;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Check if the proxyToolCalls is enabled for the given prompt or the default tool
|
|
95
|
+
* call options. The prompt options take precedence over the default options. When the
|
|
96
|
+
* proxyToolCalls is enabled the ChatModel implementation will pass the proxyToolCalls to the
|
|
97
|
+
* function call.
|
|
98
|
+
* @param chatOptions the chat options to check.
|
|
99
|
+
* @param defaultOptions the default tool call options to check.
|
|
100
|
+
* @return true if the proxyToolCalls is enabled, false otherwise.
|
|
101
|
+
*/
|
|
102
|
+
export function isProxyToolCalls(chatOptions: ChatOptions, defaultOptions: FunctionCallingOptions): boolean {
|
|
103
|
+
if (FunctionCallingOptions.is(chatOptions) && chatOptions.proxyToolCalls !== undefined) {
|
|
104
|
+
return chatOptions.proxyToolCalls;
|
|
105
|
+
}
|
|
106
|
+
return defaultOptions.proxyToolCalls ?? false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface FunctionCallbackRegister {
|
|
112
|
+
resolve(functionNames: string[]): FunctionCallback[];
|
|
113
|
+
register(functionCallback: FunctionCallback): void;
|
|
114
|
+
unregister(functionName: string): void;
|
|
115
|
+
call(functionName: string, functionArguments: string, toolContext: ToolContext): Promise<string>;
|
|
59
116
|
}
|
|
60
117
|
|
|
61
118
|
export interface PortableFunctionCallingOptions extends FunctionCallingOptions, ChatOptions {
|
|
@@ -5,7 +5,7 @@ import { Bytes } from '@celljs/core';
|
|
|
5
5
|
/**
|
|
6
6
|
* SSE utility class.
|
|
7
7
|
*/
|
|
8
|
-
export class SSEUtil {
|
|
8
|
+
export abstract class SSEUtil {
|
|
9
9
|
|
|
10
10
|
static toObservable<Data>(readableStream: ReadableStream, controller?: AbortController): Observable<StreamEvent<Data>> {
|
|
11
11
|
return new Observable<StreamEvent<Data>>(subscriber => {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ChatResponse } from '../chat';
|
|
2
|
+
import { Usage } from '../chat/metadata';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* An utility class to provide support methods handling {@link Usage}.
|
|
6
|
+
*/
|
|
7
|
+
export abstract class UsageUtil {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Accumulate usage tokens from the previous chat response to the current usage
|
|
11
|
+
* tokens.
|
|
12
|
+
* @param currentUsage the current usage.
|
|
13
|
+
* @param previousChatResponse the previous chat response.
|
|
14
|
+
* @return accumulated usage.
|
|
15
|
+
*/
|
|
16
|
+
public static getCumulativeUsage(currentUsage: Usage, previousChatResponse?: ChatResponse): Usage {
|
|
17
|
+
let usageFromPreviousChatResponse: Usage | undefined = undefined;
|
|
18
|
+
if (previousChatResponse?.metadata?.usage) {
|
|
19
|
+
usageFromPreviousChatResponse = previousChatResponse.metadata.usage;
|
|
20
|
+
} else {
|
|
21
|
+
return currentUsage;
|
|
22
|
+
}
|
|
23
|
+
// For a valid usage from previous chat response, accumulate it to the current
|
|
24
|
+
// usage.
|
|
25
|
+
if (!this.isEmpty(currentUsage)) {
|
|
26
|
+
let promptTokens = currentUsage.promptTokens ?? 0;
|
|
27
|
+
let generationTokens = currentUsage.generationTokens ?? 0;
|
|
28
|
+
let totalTokens = currentUsage.totalTokens ?? 0;
|
|
29
|
+
// Make sure to accumulate the usage from the previous chat response.
|
|
30
|
+
promptTokens += usageFromPreviousChatResponse.promptTokens ?? 0;
|
|
31
|
+
generationTokens += usageFromPreviousChatResponse.generationTokens ?? 0;
|
|
32
|
+
totalTokens += usageFromPreviousChatResponse.totalTokens ?? 0;
|
|
33
|
+
return Usage.from(promptTokens, generationTokens, totalTokens);
|
|
34
|
+
}
|
|
35
|
+
// When current usage is empty, return the usage from the previous chat response.
|
|
36
|
+
return usageFromPreviousChatResponse;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// /**
|
|
40
|
+
// * Check if the {@link Usage} is empty. Returns true when the {@link Usage} is null.
|
|
41
|
+
// * Returns true when the {@link Usage} has zero tokens.
|
|
42
|
+
// * @param usage the usage to check against.
|
|
43
|
+
// * @return the boolean value to represent if it is empty.
|
|
44
|
+
// */
|
|
45
|
+
// static isEmpty(usage: Usage | null): boolean {
|
|
46
|
+
// if (!usage) {
|
|
47
|
+
// return true;
|
|
48
|
+
// } else if (usage != null && usage.totalTokens === 0) {
|
|
49
|
+
// return true;
|
|
50
|
+
// }
|
|
51
|
+
// return false;
|
|
52
|
+
// }
|
|
53
|
+
static isEmpty(usage: Usage | null): boolean {
|
|
54
|
+
if (!usage) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|