wirejs-deploy-amplify-basic 0.0.162 → 0.0.164-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/amplify-backend-assets/backend.ts +12 -0
- package/amplify-backend-assets/constructs/realtime-service/index.ts +1 -1
- package/amplify-hosting-assets/compute/default/package.json +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/services/llm.d.ts +14 -0
- package/dist/services/llm.js +152 -0
- package/package.json +3 -2
|
@@ -213,6 +213,18 @@ const apiUrl = backend.api.resources.lambda.addFunctionUrl({
|
|
|
213
213
|
});
|
|
214
214
|
apiUrl.grantInvokeUrl(new AnyPrincipal());
|
|
215
215
|
|
|
216
|
+
backend.api.resources.lambda.addToRolePolicy(new PolicyStatement({
|
|
217
|
+
actions: [
|
|
218
|
+
'bedrock:InvokeModel',
|
|
219
|
+
'bedrock:InvokeModelWithResponseStream'
|
|
220
|
+
],
|
|
221
|
+
resources: [
|
|
222
|
+
'arn:aws:bedrock:*::foundation-model/*',
|
|
223
|
+
'arn:aws:bedrock:*:*:custom-model/*'
|
|
224
|
+
]
|
|
225
|
+
}));
|
|
226
|
+
|
|
227
|
+
|
|
216
228
|
backend.addOutput({
|
|
217
229
|
custom: {
|
|
218
230
|
api: apiUrl.url
|
|
@@ -60,7 +60,7 @@ export class RealtimeService extends Construct {
|
|
|
60
60
|
const iamProvider: AppSyncAuthProvider = { authorizationType: IAM };
|
|
61
61
|
|
|
62
62
|
realtimeService = new EventApi(this, 'realtime', {
|
|
63
|
-
apiName: `${props.appId}-${props.branchId}-realtime-api`,
|
|
63
|
+
apiName: `${props.appId.slice(0, 18)}-${props.branchId.slice(0, 18)}-realtime-api`,
|
|
64
64
|
authorizationConfig: {
|
|
65
65
|
authProviders: [iamProvider, lambdaProvider],
|
|
66
66
|
connectionAuthModeTypes: [LAMBDA],
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from 'wirejs-resources';
|
|
2
2
|
export { FileService } from './services/file.js';
|
|
3
3
|
export { AuthenticationService } from './services/authentication.js';
|
|
4
|
+
export { LLM } from './services/llm.js';
|
|
4
5
|
export { DistributedTable } from './resources/distributed-table.js';
|
|
5
6
|
export { RealtimeService } from './services/realtime.js';
|
|
6
7
|
export { BackgroundJob } from './resources/background-job.js';
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { FileService } from './services/file.js';
|
|
|
6
6
|
export { FileService } from './services/file.js';
|
|
7
7
|
import { AuthenticationService } from './services/authentication.js';
|
|
8
8
|
export { AuthenticationService } from './services/authentication.js';
|
|
9
|
+
import { LLM } from './services/llm.js';
|
|
10
|
+
export { LLM } from './services/llm.js';
|
|
9
11
|
import { DistributedTable } from './resources/distributed-table.js';
|
|
10
12
|
export { DistributedTable } from './resources/distributed-table.js';
|
|
11
13
|
import { RealtimeService } from './services/realtime.js';
|
|
@@ -21,3 +23,4 @@ overrides.FileService = FileService;
|
|
|
21
23
|
overrides.RealtimeService = RealtimeService;
|
|
22
24
|
overrides.BackgroundJob = BackgroundJob;
|
|
23
25
|
overrides.Endpoint = Endpoint;
|
|
26
|
+
overrides.LLM = LLM;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LLM as BaseLLM, LLMMessage, LLMChunk, Resource } from 'wirejs-resources';
|
|
2
|
+
export declare class LLM extends BaseLLM {
|
|
3
|
+
private bedrockClient;
|
|
4
|
+
constructor(scope: Resource | string, id: string, options: {
|
|
5
|
+
models: string[];
|
|
6
|
+
});
|
|
7
|
+
private createBedrockInstructionMessage;
|
|
8
|
+
private convertToBedrockFormat;
|
|
9
|
+
private getModelId;
|
|
10
|
+
private invokeBedrock;
|
|
11
|
+
private streamBedrock;
|
|
12
|
+
private invokeModel;
|
|
13
|
+
continueConversation(history: LLMMessage[], onChunk?: (chunk: LLMChunk) => void | Promise<void>): Promise<LLMMessage>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { LLM as BaseLLM } from 'wirejs-resources';
|
|
2
|
+
import { BedrockRuntimeClient, InvokeModelCommand, InvokeModelWithResponseStreamCommand } from '@aws-sdk/client-bedrock-runtime';
|
|
3
|
+
import { defaultProvider } from '@aws-sdk/credential-provider-node';
|
|
4
|
+
export class LLM extends BaseLLM {
|
|
5
|
+
bedrockClient;
|
|
6
|
+
constructor(scope, id, options) {
|
|
7
|
+
super(scope, id, options);
|
|
8
|
+
this.models = options.models;
|
|
9
|
+
this.bedrockClient = new BedrockRuntimeClient({
|
|
10
|
+
credentials: defaultProvider(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
createBedrockInstructionMessage(message) {
|
|
14
|
+
return {
|
|
15
|
+
role: 'assistant',
|
|
16
|
+
content: message
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
convertToBedrockFormat(messages) {
|
|
20
|
+
return messages.map(msg => ({
|
|
21
|
+
role: msg.role === 'user' ? 'user' : 'assistant',
|
|
22
|
+
content: msg.content
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
getModelId(model) {
|
|
26
|
+
// small set of convenience identifier aliases. maybe worth breaking out into
|
|
27
|
+
// a larger, shared, canonical JSON later?
|
|
28
|
+
const modelMap = {
|
|
29
|
+
'claude': 'anthropic.claude-3-haiku-20240307-v1:0',
|
|
30
|
+
'claude-haiku': 'anthropic.claude-3-haiku-20240307-v1:0',
|
|
31
|
+
'claude-sonnet': 'anthropic.claude-3-sonnet-20240229-v1:0',
|
|
32
|
+
'claude-opus': 'anthropic.claude-3-opus-20240229-v1:0',
|
|
33
|
+
'llama2': 'meta.llama2-70b-chat-v1',
|
|
34
|
+
'llama3': 'meta.llama3-70b-instruct-v1:0',
|
|
35
|
+
};
|
|
36
|
+
return modelMap[model] || model;
|
|
37
|
+
}
|
|
38
|
+
async invokeBedrock(modelId, messages, stream) {
|
|
39
|
+
const body = JSON.stringify({
|
|
40
|
+
anthropic_version: "bedrock-2023-05-31",
|
|
41
|
+
max_tokens: 10000,
|
|
42
|
+
messages: this.convertToBedrockFormat(messages)
|
|
43
|
+
});
|
|
44
|
+
if (stream) {
|
|
45
|
+
const command = new InvokeModelWithResponseStreamCommand({
|
|
46
|
+
modelId,
|
|
47
|
+
body,
|
|
48
|
+
contentType: 'application/json',
|
|
49
|
+
accept: 'application/json'
|
|
50
|
+
});
|
|
51
|
+
return await this.bedrockClient.send(command);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const command = new InvokeModelCommand({
|
|
55
|
+
modelId,
|
|
56
|
+
body,
|
|
57
|
+
contentType: 'application/json',
|
|
58
|
+
accept: 'application/json'
|
|
59
|
+
});
|
|
60
|
+
return await this.bedrockClient.send(command);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async streamBedrock(response, onChunk) {
|
|
64
|
+
let content = '';
|
|
65
|
+
if (response.body) {
|
|
66
|
+
for await (const chunk of response.body) {
|
|
67
|
+
if (chunk.chunk?.bytes) {
|
|
68
|
+
const data = JSON.parse(new TextDecoder().decode(chunk.chunk.bytes));
|
|
69
|
+
if (data.delta?.text) {
|
|
70
|
+
content += data.delta.text;
|
|
71
|
+
const llmChunk = {
|
|
72
|
+
created_at: new Date().toISOString(),
|
|
73
|
+
message: {
|
|
74
|
+
role: 'assistant',
|
|
75
|
+
content: data.delta.text
|
|
76
|
+
},
|
|
77
|
+
done: false
|
|
78
|
+
};
|
|
79
|
+
if (onChunk) {
|
|
80
|
+
try {
|
|
81
|
+
await onChunk(llmChunk);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error(error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
role: 'assistant',
|
|
93
|
+
content
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async invokeModel(model, history, onChunk, maxRetries = 10) {
|
|
97
|
+
const stream = typeof onChunk === 'function';
|
|
98
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
99
|
+
try {
|
|
100
|
+
const modelId = this.getModelId(model);
|
|
101
|
+
const response = await this.invokeBedrock(modelId, history, stream);
|
|
102
|
+
if (stream) {
|
|
103
|
+
return this.streamBedrock(response, onChunk);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const data = JSON.parse(new TextDecoder().decode(response.body));
|
|
107
|
+
return {
|
|
108
|
+
role: 'assistant',
|
|
109
|
+
content: data.content?.[0]?.text || 'No response generated'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error.name === 'ThrottlingException') {
|
|
115
|
+
console.warn(`ThrottlingException encountered for model ${model}. Retrying...`);
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, i * 1000 + Math.random() * 1000));
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
throw new Error("Exceeded max retries trying to invoke " + model);
|
|
125
|
+
}
|
|
126
|
+
async continueConversation(history, onChunk) {
|
|
127
|
+
// models are expected to be given in priority order. first one that doesn't
|
|
128
|
+
// throw a fit wins.
|
|
129
|
+
for (const model of this.models) {
|
|
130
|
+
try {
|
|
131
|
+
return await this.invokeModel(model, history, onChunk);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.log(error);
|
|
135
|
+
if (error.name === 'ValidationException' && error.message?.includes('model')) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (error.name === 'AccessDeniedException') {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return this.createBedrockInstructionMessage(`None of the attempted are not available or not enabled in your AWS account. ` +
|
|
144
|
+
`Please enable it in the AWS Bedrock console:\n\n` +
|
|
145
|
+
`1. Go to AWS Bedrock Console (https://console.aws.amazon.com/bedrock/)\n` +
|
|
146
|
+
`2. Navigate to "Model access"\n` +
|
|
147
|
+
`3. Request access to the model\n` +
|
|
148
|
+
`4. Accept the End User License Agreement (EULA)\n\n` +
|
|
149
|
+
`Available models attempted: ${this.models.join(', ')}\n` +
|
|
150
|
+
`You may need to enable these models: ${this.models.map(m => this.getModelId(m)).join(', ')}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wirejs-deploy-amplify-basic",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.164-llm",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@aws-crypto/sha256-js": "^5.2.0",
|
|
31
|
+
"@aws-sdk/client-bedrock-runtime": "^3.821.0",
|
|
31
32
|
"@aws-sdk/client-cognito-identity-provider": "^3.741.0",
|
|
32
33
|
"@aws-sdk/client-dynamodb": "^3.774.0",
|
|
33
34
|
"@aws-sdk/client-s3": "^3.738.0",
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"recursive-copy": "^2.0.14",
|
|
43
44
|
"rimraf": "^6.0.1",
|
|
44
45
|
"wirejs-dom": "^1.0.42",
|
|
45
|
-
"wirejs-resources": "^0.1.
|
|
46
|
+
"wirejs-resources": "^0.1.132-llm"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@aws-amplify/backend": "^1.14.0",
|