Skip to content

Commit 4c29353

Browse files
committed
Enhance DocumentProcessorService with Perplexity integration for simplified explanations
- Added PerplexityService to backend/src/document-processor/document-processor.module.ts for generating simplified explanations of medical documents. - Updated DocumentProcessorService in backend/src/document-processor/services/document-processor.service.ts to include logic for generating simplified explanations during document processing. - Modified DocumentProcessorController in backend/src/document-processor/controllers/document-processor.controller.ts to return simplified explanations alongside analysis results. - Enhanced unit tests in backend/src/document-processor/services/document-processor.service.spec.ts to validate the integration of PerplexityService and the new simplified explanation feature.
1 parent 32a9272 commit 4c29353

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

backend/src/document-processor/controllers/document-processor.controller.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ export class DocumentProcessorController {
8181
timestamp: new Date().toISOString(),
8282
rawExtractedText: result.extractedText,
8383
rawAnalysis: result.analysis,
84+
rawSimplifiedExplanation: result.simplifiedExplanation,
8485
},
8586
};
8687
}
8788

88-
return result.analysis;
89+
return { analysis: result.analysis, simplifiedExplanation: result.simplifiedExplanation };
8990
} catch (error: unknown) {
9091
this.logger.error(
9192
`Error processing document: ${error instanceof Error ? error.message : 'Unknown error'}`,

backend/src/document-processor/document-processor.module.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ import { ConfigModule } from '@nestjs/config';
44
import { AwsTextractService } from './services/aws-textract.service';
55
import { AwsBedrockService } from './services/aws-bedrock.service';
66
import { DocumentProcessorController } from './controllers/document-processor.controller';
7+
import { PerplexityService } from '../services/perplexity.service';
8+
import { AwsSecretsService } from '../services/aws-secrets.service';
79

810
@Module({
911
imports: [ConfigModule],
1012
controllers: [DocumentProcessorController],
11-
providers: [DocumentProcessorService, AwsTextractService, AwsBedrockService],
13+
providers: [
14+
DocumentProcessorService,
15+
AwsTextractService,
16+
AwsBedrockService,
17+
PerplexityService,
18+
AwsSecretsService,
19+
],
1220
exports: [DocumentProcessorService, AwsTextractService, AwsBedrockService],
1321
})
1422
export class DocumentProcessorModule {}

backend/src/document-processor/services/document-processor.service.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { BadRequestException } from '@nestjs/common';
22
import { DocumentProcessorService } from './document-processor.service';
33
import { AwsTextractService } from './aws-textract.service';
44
import { AwsBedrockService } from './aws-bedrock.service';
5+
import { PerplexityService } from '../../services/perplexity.service';
56
import { describe, it, expect, vi } from 'vitest';
67

78
// Mock the crypto module
@@ -44,18 +45,23 @@ describe('DocumentProcessorService', () => {
4445
},
4546
};
4647

48+
const simplifiedExplanation = 'This is a simple explanation of the medical document.';
49+
4750
// Create a new test-specific instance with proper mocking
4851
const testTextractService = { extractText: vi.fn() };
4952
const testBedrockService = { analyzeMedicalDocument: vi.fn() };
53+
const testPerplexityService = { explainMedicalText: vi.fn() };
5054

5155
// Set up mocks
5256
testTextractService.extractText.mockResolvedValue(extractedTextResult);
5357
testBedrockService.analyzeMedicalDocument.mockResolvedValue(medicalAnalysis);
58+
testPerplexityService.explainMedicalText.mockResolvedValue(simplifiedExplanation);
5459

5560
// Create a fresh service instance with our mocks
5661
const testService = new DocumentProcessorService(
5762
testTextractService as unknown as AwsTextractService,
5863
testBedrockService as unknown as AwsBedrockService,
64+
testPerplexityService as unknown as PerplexityService,
5965
);
6066

6167
// Act
@@ -67,9 +73,13 @@ describe('DocumentProcessorService', () => {
6773
extractedTextResult.rawText,
6874
userId,
6975
);
76+
expect(testPerplexityService.explainMedicalText).toHaveBeenCalledWith(
77+
extractedTextResult.rawText,
78+
);
7079
expect(result).toEqual({
7180
extractedText: extractedTextResult,
7281
analysis: medicalAnalysis,
82+
simplifiedExplanation,
7383
processingMetadata: expect.objectContaining({
7484
fileType,
7585
fileSize: fileBuffer.length,
@@ -86,6 +96,7 @@ describe('DocumentProcessorService', () => {
8696
// Create test-specific service with proper mocking
8797
const testTextractService = { extractText: vi.fn() };
8898
const testBedrockService = { analyzeMedicalDocument: vi.fn() };
99+
const testPerplexityService = { explainMedicalText: vi.fn() };
89100

90101
// Make the mock reject with an error
91102
testTextractService.extractText.mockRejectedValue(new Error('Failed to extract text'));
@@ -94,6 +105,7 @@ describe('DocumentProcessorService', () => {
94105
const testService = new DocumentProcessorService(
95106
testTextractService as unknown as AwsTextractService,
96107
testBedrockService as unknown as AwsBedrockService,
108+
testPerplexityService as unknown as PerplexityService,
97109
);
98110

99111
// Act & Assert
@@ -115,11 +127,13 @@ describe('DocumentProcessorService', () => {
115127
// Create test-specific service with proper mocking
116128
const testTextractService = { extractText: vi.fn() };
117129
const testBedrockService = { analyzeMedicalDocument: vi.fn() };
130+
const testPerplexityService = { explainMedicalText: vi.fn() };
118131

119132
// Create a fresh service instance with our mocks
120133
const testService = new DocumentProcessorService(
121134
testTextractService as unknown as AwsTextractService,
122135
testBedrockService as unknown as AwsBedrockService,
136+
testPerplexityService as unknown as PerplexityService,
123137
);
124138

125139
// Mock the processDocument method on our test service
@@ -142,6 +156,7 @@ describe('DocumentProcessorService', () => {
142156
missingInformation: [],
143157
},
144158
},
159+
simplifiedExplanation: 'Simple explanation for document 1',
145160
processingMetadata: {
146161
processingTimeMs: 100,
147162
fileType: 'application/pdf',
@@ -166,6 +181,7 @@ describe('DocumentProcessorService', () => {
166181
missingInformation: [],
167182
},
168183
},
184+
simplifiedExplanation: 'Simple explanation for document 2',
169185
processingMetadata: {
170186
processingTimeMs: 100,
171187
fileType: 'image/jpeg',
@@ -207,6 +223,7 @@ describe('DocumentProcessorService', () => {
207223
const testService = new DocumentProcessorService(
208224
{} as AwsTextractService,
209225
{} as AwsBedrockService,
226+
{} as PerplexityService,
210227
);
211228

212229
// Create a test implementation that checks for empty array

backend/src/document-processor/services/document-processor.service.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { Injectable, Logger, BadRequestException } from '@nestjs/common';
22
import { createHash } from 'crypto';
33
import { AwsTextractService, ExtractedTextResult } from './aws-textract.service';
44
import { AwsBedrockService, MedicalDocumentAnalysis } from './aws-bedrock.service';
5+
import { PerplexityService } from '../../services/perplexity.service';
56

67
/**
78
* Result interface for processed medical documents
89
*/
910
export interface ProcessedDocumentResult {
1011
extractedText: ExtractedTextResult;
1112
analysis: MedicalDocumentAnalysis;
13+
simplifiedExplanation?: string;
1214
processingMetadata: {
1315
processingTimeMs: number;
1416
fileType: string;
@@ -27,14 +29,15 @@ export class DocumentProcessorService {
2729
constructor(
2830
private readonly textractService: AwsTextractService,
2931
private readonly bedrockService: AwsBedrockService,
32+
private readonly perplexityService: PerplexityService,
3033
) {}
3134

3235
/**
3336
* Process a medical document by extracting text and performing analysis
3437
* @param fileBuffer The file buffer containing the image or PDF
3538
* @param fileType The MIME type of the file (e.g., 'image/jpeg', 'application/pdf')
3639
* @param userId The authenticated user's ID for rate limiting
37-
* @returns Processed document result with extracted text and analysis
40+
* @returns Processed document result with extracted text, analysis, and simplified explanation
3841
*/
3942
async processDocument(
4043
fileBuffer: Buffer,
@@ -64,19 +67,40 @@ export class DocumentProcessorService {
6467
userId,
6568
);
6669

70+
// Step 3: Generate simplified explanation using Perplexity
71+
let simplifiedExplanation: string | undefined;
72+
73+
try {
74+
if (analysis.metadata.isMedicalReport && extractedText.rawText) {
75+
this.logger.log('Generating simplified explanation');
76+
simplifiedExplanation = await this.perplexityService.explainMedicalText(
77+
extractedText.rawText,
78+
);
79+
this.logger.log('Simplified explanation generated successfully');
80+
}
81+
} catch (explanationError) {
82+
this.logger.error('Error generating simplified explanation', {
83+
error: explanationError instanceof Error ? explanationError.message : 'Unknown error',
84+
});
85+
// We don't want to fail the entire process if explanation fails
86+
simplifiedExplanation = undefined;
87+
}
88+
6789
const processingTime = Date.now() - startTime;
6890

6991
this.logger.log(`Document processing completed in ${processingTime}ms`, {
7092
isMedicalReport: analysis.metadata.isMedicalReport,
7193
confidence: analysis.metadata.confidence,
7294
keyTermCount: analysis.keyMedicalTerms.length,
7395
labValueCount: analysis.labValues.length,
96+
hasExplanation: !!simplifiedExplanation,
7497
});
7598

7699
// Return combined result
77100
return {
78101
extractedText,
79102
analysis,
103+
simplifiedExplanation,
80104
processingMetadata: {
81105
processingTimeMs: processingTime,
82106
fileType,
@@ -149,6 +173,7 @@ export class DocumentProcessorService {
149173
missingInformation: ['Document processing failed'],
150174
},
151175
},
176+
simplifiedExplanation: undefined,
152177
processingMetadata: {
153178
processingTimeMs: 0,
154179
fileType: doc.type,

0 commit comments

Comments
 (0)