@@ -2,6 +2,8 @@ import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedroc
22import { fetchAuthSession } from '@aws-amplify/auth' ;
33import { REGION } from '../../config/aws-config' ;
44
5+ export const CONTENT_FILTERED_MESSAGE = "I couldn't find an answer. Please try rephrasing your question or consult your healthcare provider." ;
6+
57export interface ChatMessage {
68 role : 'user' | 'assistant' | 'system' ;
79 content : string ;
@@ -14,11 +16,24 @@ export interface ChatSession {
1416 updatedAt : Date ;
1517}
1618
19+ // Interfaces for Bedrock API responses
20+ interface BedrockResult {
21+ tokenCount : number ;
22+ outputText : string ;
23+ completionReason : 'CONTENT_FILTERED' | 'COMPLETE' | 'LENGTH' | 'STOP_SEQUENCE' | string ;
24+ }
25+
26+ interface BedrockResponse {
27+ inputTextTokenCount : number ;
28+ results : BedrockResult [ ] ;
29+ }
30+
1731class BedrockService {
1832 private client : BedrockRuntimeClient | null = null ;
1933 private readonly MODEL_ID = 'amazon.titan-text-lite-v1' ;
2034 private sessions : Map < string , ChatSession > = new Map ( ) ;
2135 private isTestEnvironment : boolean ;
36+ private contentFilteredCount : number = 0 ; // Track number of filtered responses
2237
2338 constructor ( ) {
2439 // Check if we're in a test environment (Node.js environment with no window)
@@ -67,6 +82,37 @@ class BedrockService {
6782 }
6883 }
6984
85+ private handleBedrockResponse ( parsedResponse : BedrockResponse , userPrompt ?: string ) : string {
86+ // Check if we have results
87+ if ( ! parsedResponse . results || ! parsedResponse . results . length ) {
88+ throw new Error ( 'Invalid response structure: missing results' ) ;
89+ }
90+
91+ const result = parsedResponse . results [ 0 ] ;
92+
93+ // Check for content filtering
94+ if ( result . completionReason === "CONTENT_FILTERED" ) {
95+ // Increment counter for analytics
96+ this . contentFilteredCount ++ ;
97+
98+ // Log for debugging if we have the original prompt
99+ if ( userPrompt ) {
100+ console . warn ( `Content filtered response #${ this . contentFilteredCount } for prompt: "${ userPrompt . substring ( 0 , 100 ) } ..."` ) ;
101+ } else {
102+ console . warn ( `Content filtered response #${ this . contentFilteredCount } ` ) ;
103+ }
104+
105+ return CONTENT_FILTERED_MESSAGE ;
106+ }
107+
108+ // Check for other potential failure reasons
109+ if ( result . completionReason && result . completionReason !== "COMPLETE" ) {
110+ console . warn ( `Incomplete response with reason: ${ result . completionReason } ` ) ;
111+ }
112+
113+ return result . outputText ;
114+ }
115+
70116 private async invokeModel ( prompt : string ) : Promise < string > {
71117 // In test environment, return a mock response
72118 if ( this . isTestEnvironment || ! this . client ) {
@@ -92,8 +138,9 @@ class BedrockService {
92138 const command = new InvokeModelCommand ( input ) ;
93139 const response = await this . client . send ( command ) ;
94140 const responseBody = new TextDecoder ( ) . decode ( response . body ) ;
95- const parsedResponse = JSON . parse ( responseBody ) ;
96- return parsedResponse . results [ 0 ] . outputText ;
141+ const parsedResponse = JSON . parse ( responseBody ) as BedrockResponse ;
142+
143+ return this . handleBedrockResponse ( parsedResponse , prompt ) ;
97144 } catch ( error ) {
98145 console . error ( 'Error invoking Bedrock model:' , error ) ;
99146 throw error ;
@@ -162,6 +209,11 @@ class BedrockService {
162209 public getAllSessions ( ) : ChatSession [ ] {
163210 return Array . from ( this . sessions . values ( ) ) ;
164211 }
212+
213+ // Add a method to get stats
214+ public getContentFilteredStats ( ) : { count : number } {
215+ return { count : this . contentFilteredCount } ;
216+ }
165217}
166218
167219export const bedrockService = new BedrockService ( ) ;
0 commit comments