Skip to content

Commit 5c5cbbf

Browse files
authored
Merge pull request #45 from ModusCreateOrg/ADE-152
[ADE-152] Add AWS Textract, AWS Bedrock services with medical information extraction & analysis functionalities
2 parents bda3d41 + fbc5c20 commit 5c5cbbf

19 files changed

+7147
-1343
lines changed

backend/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ This script sets a resource policy that:
8787
1. Allows only authenticated Cognito users to access your API
8888
2. Denies any non-HTTPS requests to your API
8989

90-
If you need more complex permissions, you can modify the policy object in the script.
90+
If you need more complex permissions, you can modify the policy object in the script.

backend/package-lock.json

+3,464-1,319
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
"cdk:synth": "dotenv -- npx cdk synth"
2828
},
2929
"dependencies": {
30+
"@aws-sdk/client-bedrock": "^3.782.0",
31+
"@aws-sdk/client-bedrock-runtime": "^3.782.0",
3032
"@aws-sdk/client-dynamodb": "^3.758.0",
3133
"@aws-sdk/client-secrets-manager": "^3.758.0",
34+
"@aws-sdk/client-textract": "^3.782.0",
3235
"@aws-sdk/util-dynamodb": "^3.758.0",
3336
"@nestjs/common": "^10.0.0",
3437
"@nestjs/config": "^3.1.1",
@@ -69,10 +72,11 @@
6972
"@types/jest": "^29.5.14",
7073
"@types/jsonwebtoken": "^9.0.4",
7174
"@types/jwk-to-pem": "^2.0.2",
75+
"@types/multer": "^1.4.12",
7276
"@types/node": "^20.12.7",
7377
"@typescript-eslint/eslint-plugin": "^7.9.0",
7478
"@typescript-eslint/parser": "^7.9.0",
75-
"@vitest/coverage-c8": "^0.33.0",
79+
"@vitest/coverage-v8": "^3.1.1",
7680
"aws-cdk": "2.139.0",
7781
"aws-cdk-lib": "^2.185.0",
7882
"dotenv-cli": "^8.0.0",
@@ -89,7 +93,7 @@
8993
"tsconfig-paths": "^4.2.0",
9094
"typescript": "^5.4.5",
9195
"vite-tsconfig-paths": "^4.2.0",
92-
"vitest": "^0.33.0"
96+
"vitest": "^3.1.1"
9397
},
9498
"peerDependencies": {
9599
"aws-cdk-lib": "^2.185.0"

backend/src/app.module.spec.ts

+33
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ import { ConfigModule } from '@nestjs/config';
44
import { JwtModule } from '@nestjs/jwt';
55
import { ReportsService } from './reports/reports.service';
66
import { vi, describe, it, expect } from 'vitest';
7+
import configuration from './config/configuration';
8+
import { PerplexityService } from './services/perplexity.service';
9+
import { AwsSecretsService } from './services/aws-secrets.service';
10+
import { AwsTextractService } from './document-processor/services/aws-textract.service';
11+
import { AwsBedrockService } from './document-processor/services/aws-bedrock.service';
712

813
describe('AppModule', () => {
914
it('should compile the module', async () => {
1015
const module = await Test.createTestingModule({
1116
imports: [
1217
ConfigModule.forRoot({
1318
isGlobal: true,
19+
load: [configuration],
1420
}),
1521
JwtModule.register({
1622
secret: 'test-secret',
@@ -26,6 +32,33 @@ describe('AppModule', () => {
2632
findOne: vi.fn().mockResolvedValue({}),
2733
updateStatus: vi.fn().mockResolvedValue({}),
2834
})
35+
.overrideProvider(PerplexityService)
36+
.useValue({
37+
askQuestion: vi.fn().mockResolvedValue({}),
38+
})
39+
.overrideProvider(AwsSecretsService)
40+
.useValue({
41+
getPerplexityApiKey: vi.fn().mockResolvedValue('test-api-key'),
42+
})
43+
.overrideProvider(AwsTextractService)
44+
.useValue({
45+
extractText: vi.fn().mockResolvedValue({}),
46+
processBatch: vi.fn().mockResolvedValue([]),
47+
})
48+
.overrideProvider(AwsBedrockService)
49+
.useValue({
50+
generateResponse: vi.fn().mockResolvedValue('test response'),
51+
analyzeMedicalDocument: vi.fn().mockResolvedValue({
52+
keyMedicalTerms: [],
53+
labValues: [],
54+
diagnoses: [],
55+
metadata: {
56+
isMedicalReport: true,
57+
confidence: 0.9,
58+
missingInformation: [],
59+
},
60+
}),
61+
})
2962
.compile();
3063

3164
expect(module).toBeDefined();

backend/src/app.module.ts

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { UserController } from './user/user.controller';
1010
import { ReportsModule } from './reports/reports.module';
1111
import { HealthController } from './health/health.controller';
1212
import { AuthMiddleware } from './auth/auth.middleware';
13+
import { DocumentProcessorModule } from './document-processor/document-processor.module';
1314

1415
@Module({
1516
imports: [
@@ -18,6 +19,7 @@ import { AuthMiddleware } from './auth/auth.middleware';
1819
load: [configuration],
1920
}),
2021
ReportsModule,
22+
DocumentProcessorModule,
2123
],
2224
controllers: [AppController, HealthController, PerplexityController, UserController],
2325
providers: [AppService, AwsSecretsService, PerplexityService],

backend/src/config/configuration.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import configuration from './configuration';
44
describe('Configuration', () => {
55
// Save original environment
66
const originalEnv = { ...process.env };
7-
7+
88
beforeEach(() => {
99
// Clear environment variables before each test
1010
process.env = {};
11-
11+
1212
// Set NODE_ENV to test for the first test
1313
process.env.NODE_ENV = 'test';
1414
});
@@ -20,7 +20,7 @@ describe('Configuration', () => {
2020

2121
it('should return default values when no env variables are set', () => {
2222
const config = configuration();
23-
23+
2424
expect(config.port).toBe(3000);
2525
expect(config.environment).toBe('test');
2626
expect(config.aws.region).toBe('us-east-1'); // Default value in configuration.ts
@@ -50,4 +50,4 @@ describe('Configuration', () => {
5050
delete process.env.AWS_COGNITO_USER_POOL_ID;
5151
delete process.env.AWS_COGNITO_CLIENT_ID;
5252
});
53-
});
53+
});

backend/src/config/configuration.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,27 @@ export default () => ({
88
clientId: process.env.AWS_COGNITO_CLIENT_ID,
99
},
1010
secretsManager: {
11-
perplexityApiKeySecret: process.env.PERPLEXITY_API_KEY_SECRET_NAME || 'medical-reports-explainer/perplexity-api-key',
11+
perplexityApiKeySecret:
12+
process.env.PERPLEXITY_API_KEY_SECRET_NAME ||
13+
'medical-reports-explainer/perplexity-api-key',
1214
},
1315
aws: {
1416
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
1517
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
16-
}
18+
sessionToken: process.env.AWS_SESSION_TOKEN,
19+
},
20+
bedrock: {
21+
model: process.env.AWS_BEDROCK_MODEL || 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
22+
maxTokens: parseInt(process.env.AWS_BEDROCK_MAX_TOKENS || '2048', 10),
23+
inferenceProfileArn:
24+
process.env.AWS_BEDROCK_INFERENCE_PROFILE_ARN ||
25+
'arn:aws:bedrock:us-east-1:841162674562:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0',
26+
requestsPerMinute: parseInt(process.env.AWS_BEDROCK_REQUESTS_PER_MINUTE || '20', 20),
27+
},
28+
textract: {
29+
maxBatchSize: parseInt(process.env.AWS_TEXTRACT_MAX_BATCH_SIZE || '10', 10),
30+
documentRequestsPerMinute: parseInt(process.env.AWS_TEXTRACT_DOCS_PER_MINUTE || '20', 20),
31+
},
1732
},
1833
perplexity: {
1934
apiBaseUrl: 'https://api.perplexity.ai',

0 commit comments

Comments
 (0)