Skip to content

Commit 124d7a4

Browse files
committed
chore: wip
chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip
1 parent f228072 commit 124d7a4

File tree

24 files changed

+217
-102
lines changed

24 files changed

+217
-102
lines changed

bun.lockb

-28 KB
Binary file not shown.

bunfig.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,4 @@ savePath = "bun.lockb"
4747

4848
# whether to save the lockfile to disk
4949
save = true
50-
51-
preload = ["./storage/framework/.stacks/core/bun-plugin-yaml/src/index.ts"]
50+
preload = [ "./storage/framework/.stacks/core/bun-plugin-yaml/src/index.ts" ]

config/cloud.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@ export default {
3131
},
3232
},
3333

34-
deploy: {
35-
docs: true, // deploys docs
36-
api: true, // deploys api
37-
fileSystem: true, // enables file system
38-
},
34+
ai: true, // deploys AI endpoints
35+
docs: true, // deploys project documentation
36+
api: true, // deploys project API
37+
fileSystem: true, // enables file system
3938

4039
// compute: {},
41-
4240
// queues: false,
4341
// queue-concurrency: 50
4442
} satisfies CloudConfig
File renamed without changes.

storage/framework/.stacks/core/cloud/src/cloud/ai.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,22 @@ export class AiStack {
3636
bedrockAccessRole.addToPolicy(bedrockAccessPolicy)
3737

3838
const aiLambda = new lambda.Function(scope, 'AiFunction', {
39-
functionName: `${props.slug}-${props.appEnv}-ai`,
39+
functionName: `${props.slug}-${props.appEnv}-ai-ask`,
4040
description: 'Lambda function to invoke the AI model',
4141
runtime: lambda.Runtime.NODEJS_20_X,
4242
handler: 'index.handler',
43-
code: lambda.Code.fromAsset('src/cloud/lambda'), // path relative to the cloud root package dir
43+
code: lambda.Code.fromAsset('src/cloud/lambda/ask'), // path relative to the cloud root package dir
44+
layers: [awsSdkLayer],
45+
role: bedrockAccessRole,
46+
timeout: Duration.seconds(30),
47+
})
48+
49+
const summarizeLambda = new lambda.Function(scope, 'AiFunction', {
50+
functionName: `${props.slug}-${props.appEnv}-ai-summarize`,
51+
description: 'Lambda function to summarize any given text',
52+
runtime: lambda.Runtime.NODEJS_20_X,
53+
handler: 'index.handler',
54+
code: lambda.Code.fromAsset('src/cloud/lambda/summarize'),
4455
layers: [awsSdkLayer],
4556
role: bedrockAccessRole,
4657
timeout: Duration.seconds(30),

storage/framework/.stacks/core/cloud/src/cloud/cdn.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,11 @@ export class CdnStack {
186186
}
187187

188188
shouldDeployApi() {
189-
return config.cloud.deploy?.api
189+
return config.cloud.api
190190
}
191191

192192
apiBehaviorOptions(scope: Construct, props: CdnStackProps): Record<string, cloudfront.BehaviorOptions> {
193-
const origin = (path: '/api' | '/api/*' = '/api') => new origins.HttpOrigin(props.lb.loadBalancerDnsName, {
193+
const origin = new origins.HttpOrigin(props.lb.loadBalancerDnsName, {
194194
originPath: path,
195195
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
196196
})
@@ -201,15 +201,15 @@ export class CdnStack {
201201

202202
return {
203203
'/api': {
204-
origin: origin(),
204+
origin,
205205
compress: true,
206206
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
207207
// cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
208208
cachePolicy: this.setApiCachePolicy(scope),
209209
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
210210
},
211211
'/api/*': {
212-
origin: origin('/api/*'),
212+
origin,
213213
compress: true,
214214
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
215215
// cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
@@ -247,32 +247,36 @@ export class CdnStack {
247247
}
248248

249249
aiBehaviorOptions(scope: Construct): Record<string, cloudfront.BehaviorOptions> {
250+
// const url = new URL()
251+
250252
return {
251253
'/ai/ask': {
252-
origin: new origins.HttpOrigin('juyejkyfu5.execute-api.us-east-1.amazonaws.com', {
254+
origin: new origins.HttpOrigin('9qp44a2b7e.execute-api.us-east-1.amazonaws.com', {
253255
originPath: '/prod',
254256
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
255257
}),
256258
compress: false,
257259
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
258260
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
259-
cachePolicy: this.setApiCachePolicy(scope),
260-
},
261-
'/ai/ask/*': {
262-
origin: new origins.HttpOrigin('juyejkyfu5.execute-api.us-east-1.amazonaws.com', {
263-
originPath: '/prod',
264-
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTPS_ONLY,
261+
cachePolicy: new cloudfront.CachePolicy(scope, 'ApiCachePolicy', {
262+
comment: 'Stacks AI Cache Policy',
263+
cachePolicyName: `${this.props.slug}-${this.props.appEnv}-ai-cache-policy`,
264+
defaultTtl: Duration.seconds(0),
265+
// minTtl: config.cloud.cdn?.minTtl ? Duration.seconds(config.cloud.cdn.minTtl) : undefined,
266+
cookieBehavior: cloudfront.CacheCookieBehavior.none(),
267+
headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Accept', 'x-api-key', 'Authorization', 'Content-Type'),
268+
queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
265269
}),
266-
compress: false,
267-
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
268-
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
269-
cachePolicy: this.setApiCachePolicy(scope),
270270
},
271+
// '/ai/ask/*': {
272+
// origin,
273+
// compress: false,
274+
// allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
275+
// viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
276+
// cachePolicy: this.setApiCachePolicy(scope),
277+
// },
271278
// '/ai/summary': {
272-
// origin: new origins.HttpOrigin('s5p93gkv25.execute-api.us-east-1.amazonaws.com', {
273-
// originPath: '/prompt',
274-
// protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
275-
// }),
279+
// origin,
276280
// compress: false,
277281
// allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
278282
// viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
@@ -282,7 +286,7 @@ export class CdnStack {
282286
}
283287

284288
shouldDeployAiEndpoints() {
285-
return true
289+
return config.cloud.ai
286290
}
287291

288292
shouldDeployDocs() {

storage/framework/.stacks/core/cloud/src/cloud/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export class Cloud extends Stack {
6969
certificate: security.certificate,
7070
})
7171

72+
new AiStack(this, props)
73+
7274
const cdn = new CdnStack(this, {
7375
...props,
7476
publicBucket: storage.publicBucket,
@@ -85,7 +87,5 @@ export class Cloud extends Stack {
8587
privateBucket: storage.privateBucket,
8688
cdn: cdn.distribution,
8789
})
88-
89-
new AiStack(this, props)
9090
}
9191
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { APIGatewayEvent, APIGatewayProxyHandler } from 'aws-cdk-lib/aws-lambda'
2+
import type { InvokeModelResponse } from '@aws-sdk/client-bedrock-runtime'
3+
import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime'
4+
5+
const bedrockClient = new BedrockRuntimeClient()
6+
7+
export const handler: APIGatewayProxyHandler = async (event: APIGatewayEvent, context) => {
8+
const body = JSON.parse(event.body || '')
9+
console.log('Body', event.body)
10+
11+
const input = {
12+
modelId: 'amazon.titan-text-lite-v1',
13+
contentType: 'application/json',
14+
accept: '*/*',
15+
body: JSON.stringify({
16+
inputText: `Summarise the following text: "${body.inputText || ''}"`,
17+
textGenerationConfig: {
18+
maxTokenCount: 512,
19+
stopSequences: [],
20+
temperature: 0,
21+
topP: 0.9,
22+
},
23+
}),
24+
}
25+
const rawResponse: InvokeModelResponse = await bedrockClient.send(new InvokeModelCommand(input))
26+
const modelResponse = JSON.parse(
27+
new TextDecoder().decode(rawResponse.body),
28+
) as {
29+
inputTextTokenCount: number
30+
results: [{
31+
tokenCount: number
32+
outputText: string
33+
completionReason: string
34+
}]
35+
}
36+
const summary = modelResponse.results[0].outputText
37+
38+
return {
39+
statusCode: 200,
40+
body: JSON.stringify({ summary }),
41+
}
42+
}

storage/framework/.stacks/core/cloud/src/helpers.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -193,30 +193,33 @@ export async function deleteIamUsers() {
193193
const iam = new IAM({ region: 'us-east-1' })
194194
const data = await iam.listUsers({})
195195
const teamName = slug(config.team.name)
196-
const users = data.Users?.filter(user => user.UserName?.includes(teamName)) || []
196+
const users = data.Users?.filter((user) => {
197+
const userNameLower = user.UserName?.toLowerCase()
198+
return userNameLower !== 'stacks' && userNameLower !== teamName.toLowerCase() && userNameLower?.includes(teamName.toLowerCase())
199+
}) || []
197200

198201
if (!users || users.length === 0)
199202
return ok(`No Stacks IAM users found for team ${teamName}`)
200203

201204
const promises = users.map(async (user) => {
202-
const userName = user.UserName || '';
205+
const userName = user.UserName || ''
203206
console.log(`Deleting IAM user: ${userName}`)
204207

205208
// Get the list of policies attached to the user
206-
const policies = await iam.listAttachedUserPolicies({ UserName: userName });
209+
const policies = await iam.listAttachedUserPolicies({ UserName: userName })
207210

208211
// Detach each policy
209212
await Promise.all(policies.AttachedPolicies?.map(policy =>
210-
iam.detachUserPolicy({ UserName: userName, PolicyArn: policy.PolicyArn || '' })
211-
) || []);
213+
iam.detachUserPolicy({ UserName: userName, PolicyArn: policy.PolicyArn || '' }),
214+
) || [])
212215

213216
// Get the list of access keys for the user
214-
const accessKeys = await iam.listAccessKeys({ UserName: userName });
217+
const accessKeys = await iam.listAccessKeys({ UserName: userName })
215218

216219
// Delete each access key
217220
await Promise.all(accessKeys.AccessKeyMetadata?.map(key =>
218-
iam.deleteAccessKey({ UserName: userName, AccessKeyId: key.AccessKeyId || '' })
219-
) || []);
221+
iam.deleteAccessKey({ UserName: userName, AccessKeyId: key.AccessKeyId || '' }),
222+
) || [])
220223

221224
// Now delete the user
222225
return iam.deleteUser({ UserName: userName })
@@ -563,7 +566,7 @@ export async function getOrCreateTimestamp(): Promise<string> {
563566
}
564567
catch (error: any) {
565568
const timestamp = new Date().getTime().toString()
566-
log.info(`Creating timestamp parameter ${parameterName} with value ${timestamp}`)
569+
log.debug(`Creating timestamp parameter ${parameterName} with value ${timestamp}`)
567570
await ssm.putParameter({
568571
Name: parameterName,
569572
Value: timestamp,

0 commit comments

Comments
 (0)