wirejs-deploy-amplify-basic 0.1.148-llm → 0.1.150-llm
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/dist/services/llm.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { LLM as BaseLLM, LLMMessage, ContinueConversationOptions, Resource } from 'wirejs-resources';
|
|
1
|
+
import { LLM as BaseLLM, LLMMessage, ContinueConversationOptions, ToolDefinition, Resource } from 'wirejs-resources';
|
|
2
2
|
export declare class LLM extends BaseLLM {
|
|
3
3
|
private bedrockClient;
|
|
4
4
|
constructor(scope: Resource | string, id: string, options: {
|
|
5
5
|
models: string[];
|
|
6
6
|
systemPrompt?: string;
|
|
7
|
+
targetContextSize?: number;
|
|
8
|
+
tools?: ToolDefinition[];
|
|
7
9
|
});
|
|
8
10
|
private createBedrockInstructionMessage;
|
|
9
11
|
private convertToBedrockFormat;
|
|
@@ -11,5 +13,5 @@ export declare class LLM extends BaseLLM {
|
|
|
11
13
|
private invokeBedrock;
|
|
12
14
|
private streamBedrock;
|
|
13
15
|
private invokeModel;
|
|
14
|
-
continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, }: ContinueConversationOptions): Promise<LLMMessage>;
|
|
16
|
+
continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, models, tools, }: ContinueConversationOptions): Promise<LLMMessage>;
|
|
15
17
|
}
|
package/dist/services/llm.js
CHANGED
|
@@ -18,12 +18,40 @@ export class LLM extends BaseLLM {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
convertToBedrockFormat(messages) {
|
|
21
|
-
return messages.map(msg =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
return messages.map(msg => {
|
|
22
|
+
if (msg.role === 'tool') {
|
|
23
|
+
return {
|
|
24
|
+
role: 'user',
|
|
25
|
+
content: [{
|
|
26
|
+
toolResult: {
|
|
27
|
+
toolUseId: msg.tool_call_id,
|
|
28
|
+
content: [{ text: msg.content }]
|
|
29
|
+
}
|
|
30
|
+
}]
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else if (msg.role === 'assistant' && 'tool_calls' in msg && msg.tool_calls) {
|
|
34
|
+
return {
|
|
35
|
+
role: 'assistant',
|
|
36
|
+
content: [
|
|
37
|
+
...(msg.content ? [{ text: msg.content }] : []),
|
|
38
|
+
...msg.tool_calls.map(tc => ({
|
|
39
|
+
toolUse: {
|
|
40
|
+
toolUseId: tc.id || `tool_${Date.now()}_${Math.random()}`,
|
|
41
|
+
name: tc.function.name,
|
|
42
|
+
input: tc.function.arguments
|
|
43
|
+
}
|
|
44
|
+
}))
|
|
45
|
+
]
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return {
|
|
50
|
+
role: msg.role,
|
|
51
|
+
content: [{ text: msg.content }]
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
27
55
|
}
|
|
28
56
|
getModelId(model) {
|
|
29
57
|
// small set of convenience identifier aliases. maybe worth breaking out into
|
|
@@ -39,14 +67,26 @@ export class LLM extends BaseLLM {
|
|
|
39
67
|
};
|
|
40
68
|
return modelMap[model] || model;
|
|
41
69
|
}
|
|
42
|
-
async invokeBedrock(modelId, systemPrompt, messages, stream, abortSignal) {
|
|
70
|
+
async invokeBedrock(modelId, systemPrompt, messages, stream, tools, abortSignal) {
|
|
71
|
+
const toolConfig = tools && tools.length > 0 ? {
|
|
72
|
+
tools: tools.map(tool => ({
|
|
73
|
+
toolSpec: {
|
|
74
|
+
name: tool.name,
|
|
75
|
+
description: tool.description,
|
|
76
|
+
inputSchema: {
|
|
77
|
+
json: tool.parameters
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}))
|
|
81
|
+
} : undefined;
|
|
43
82
|
if (stream) {
|
|
44
83
|
const command = new ConverseStreamCommand({
|
|
45
84
|
modelId,
|
|
46
85
|
messages: this.convertToBedrockFormat(messages),
|
|
47
86
|
system: systemPrompt ? [{
|
|
48
87
|
text: systemPrompt
|
|
49
|
-
}] : undefined
|
|
88
|
+
}] : undefined,
|
|
89
|
+
toolConfig
|
|
50
90
|
});
|
|
51
91
|
return await this.bedrockClient.send(command, { abortSignal });
|
|
52
92
|
}
|
|
@@ -56,7 +96,8 @@ export class LLM extends BaseLLM {
|
|
|
56
96
|
messages: this.convertToBedrockFormat(messages),
|
|
57
97
|
system: systemPrompt ? [{
|
|
58
98
|
text: systemPrompt
|
|
59
|
-
}] : undefined
|
|
99
|
+
}] : undefined,
|
|
100
|
+
toolConfig
|
|
60
101
|
});
|
|
61
102
|
return await this.bedrockClient.send(command, { abortSignal });
|
|
62
103
|
}
|
|
@@ -65,6 +106,8 @@ export class LLM extends BaseLLM {
|
|
|
65
106
|
if (!response.stream)
|
|
66
107
|
return null;
|
|
67
108
|
let content = '';
|
|
109
|
+
let tool_calls = [];
|
|
110
|
+
let currentToolCall = null;
|
|
68
111
|
for await (const chunk of response.stream) {
|
|
69
112
|
// Check if request was aborted
|
|
70
113
|
if (abortSignal?.aborted) {
|
|
@@ -90,29 +133,89 @@ export class LLM extends BaseLLM {
|
|
|
90
133
|
}
|
|
91
134
|
}
|
|
92
135
|
}
|
|
136
|
+
// Handle tool use start
|
|
137
|
+
if (chunk.contentBlockStart?.start?.toolUse) {
|
|
138
|
+
const toolUse = chunk.contentBlockStart.start.toolUse;
|
|
139
|
+
currentToolCall = {
|
|
140
|
+
id: toolUse.toolUseId,
|
|
141
|
+
function: {
|
|
142
|
+
name: toolUse.name || '',
|
|
143
|
+
arguments: {}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Handle tool use delta (input parameters)
|
|
148
|
+
if (chunk.contentBlockDelta?.delta?.toolUse?.input && currentToolCall) {
|
|
149
|
+
// The input from Bedrock is a string that needs to be parsed as JSON
|
|
150
|
+
const inputString = chunk.contentBlockDelta.delta.toolUse.input;
|
|
151
|
+
try {
|
|
152
|
+
const parsedInput = JSON.parse(inputString);
|
|
153
|
+
if (parsedInput && typeof parsedInput === 'object') {
|
|
154
|
+
currentToolCall.function.arguments = {
|
|
155
|
+
...currentToolCall.function.arguments,
|
|
156
|
+
...parsedInput
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
console.warn('Failed to parse tool input JSON:', inputString, error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Handle tool use stop (finalize tool call)
|
|
165
|
+
if (chunk.contentBlockStop?.contentBlockIndex !== undefined && currentToolCall) {
|
|
166
|
+
tool_calls.push(currentToolCall);
|
|
167
|
+
currentToolCall = null;
|
|
168
|
+
}
|
|
93
169
|
}
|
|
94
|
-
|
|
170
|
+
const result = {
|
|
95
171
|
role: 'assistant',
|
|
96
172
|
content
|
|
97
173
|
};
|
|
174
|
+
if (tool_calls.length > 0) {
|
|
175
|
+
result.tool_calls = tool_calls;
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
98
178
|
}
|
|
99
|
-
async invokeModel(model, systemPrompt, history, onChunk, abortSignal, maxRetries = 10) {
|
|
179
|
+
async invokeModel(model, systemPrompt, history, onChunk, abortSignal, tools, maxRetries = 10) {
|
|
100
180
|
const stream = typeof onChunk === 'function';
|
|
101
181
|
for (let i = 0; i < maxRetries; i++) {
|
|
102
182
|
try {
|
|
103
183
|
const modelId = this.getModelId(model);
|
|
104
184
|
if (modelId !== model)
|
|
105
185
|
console.log(`Mapped ${model} to ${modelId}`);
|
|
106
|
-
const response = await this.invokeBedrock(modelId, systemPrompt, history, stream, abortSignal);
|
|
186
|
+
const response = await this.invokeBedrock(modelId, systemPrompt, history, stream, tools, abortSignal);
|
|
107
187
|
if (stream) {
|
|
108
188
|
return this.streamBedrock(response, onChunk, abortSignal);
|
|
109
189
|
}
|
|
110
190
|
else {
|
|
111
|
-
|
|
112
|
-
|
|
191
|
+
// Handle non-streaming response with potential tool calls
|
|
192
|
+
const content = response.output?.message?.content;
|
|
193
|
+
let resultContent = '';
|
|
194
|
+
let tool_calls = [];
|
|
195
|
+
if (content) {
|
|
196
|
+
for (const block of content) {
|
|
197
|
+
if (block.text) {
|
|
198
|
+
resultContent += block.text;
|
|
199
|
+
}
|
|
200
|
+
else if (block.toolUse) {
|
|
201
|
+
tool_calls.push({
|
|
202
|
+
id: block.toolUse.toolUseId,
|
|
203
|
+
function: {
|
|
204
|
+
name: block.toolUse.name,
|
|
205
|
+
arguments: block.toolUse.input || {}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const result = {
|
|
113
212
|
role: 'assistant',
|
|
114
|
-
content:
|
|
213
|
+
content: resultContent || 'No response generated'
|
|
115
214
|
};
|
|
215
|
+
if (tool_calls.length > 0) {
|
|
216
|
+
result.tool_calls = tool_calls;
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
116
219
|
}
|
|
117
220
|
}
|
|
118
221
|
catch (error) {
|
|
@@ -131,7 +234,7 @@ export class LLM extends BaseLLM {
|
|
|
131
234
|
}
|
|
132
235
|
throw new Error("Exceeded max retries trying to invoke " + model);
|
|
133
236
|
}
|
|
134
|
-
async continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, }) {
|
|
237
|
+
async continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, models, tools, }) {
|
|
135
238
|
const controller = new AbortController();
|
|
136
239
|
let timeoutId;
|
|
137
240
|
if (timeoutSeconds) {
|
|
@@ -142,9 +245,9 @@ export class LLM extends BaseLLM {
|
|
|
142
245
|
try {
|
|
143
246
|
// models are expected to be given in priority order. first one that doesn't
|
|
144
247
|
// throw a fit wins.
|
|
145
|
-
for (const model of this.models) {
|
|
248
|
+
for (const model of models ?? this.models) {
|
|
146
249
|
try {
|
|
147
|
-
const result = await this.invokeModel(model, (systemPrompt ?? this.systemPrompt) ?? '', history, onChunk, controller.signal);
|
|
250
|
+
const result = await this.invokeModel(model, (systemPrompt ?? this.systemPrompt) ?? '', history, onChunk, controller.signal, tools ?? this.tools);
|
|
148
251
|
if (!result)
|
|
149
252
|
throw new Error("No response from model.");
|
|
150
253
|
if (timeoutId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wirejs-deploy-amplify-basic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.150-llm",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"recursive-copy": "^2.0.14",
|
|
45
45
|
"rimraf": "^6.0.1",
|
|
46
46
|
"wirejs-dom": "^1.0.44",
|
|
47
|
-
"wirejs-resources": "^0.1.
|
|
47
|
+
"wirejs-resources": "^0.1.150-llm"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@aws-amplify/backend": "^1.14.0",
|