import os import json import gradio as gr import boto3 from datetime import datetime # Load secrets from environment AWS_REGION = os.getenv("AWS_REGION") AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY") # Initialize Bedrock client bedrock_runtime = boto3.client( service_name='bedrock-runtime', region_name=AWS_REGION, aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY ) # Global state to store claim data claim_data = { "policy_number": None, "claimant_name": None, "dob": None, "treatment_date": None, "reason": None, "amount": None, "pending_dob_confirmation": None # Track DOB confirmation } # Function to validate date format (YYYY-MM-DD) def is_valid_date(date_str): try: datetime.strptime(date_str, "%Y-%m-%d") return True except ValueError: return False # Function to check if all fields are filled def all_fields_filled(): return all(value is not None for key, value in claim_data.items() if key != "pending_dob_confirmation") # Function to reset claim data for a new claim def reset_claim_data(): global claim_data claim_data = { "policy_number": None, "claimant_name": None, "dob": None, "treatment_date": None, "reason": None, "amount": None, "pending_dob_confirmation": None } # Chat function with Claude def chat_with_claude(message, history): global claim_data # Base prompt for Claude base_prompt = """ You are an Insurance Claim Form Assistant. Your task is to collect and validate: policy number, claimant's name, date of birth, date of treatment, reason for claim, and amount claimed. Current data: {current_data} Follow these steps: 1. **Parse Input**: Extract fields from the user's message: "{user_message}". 2. **Handle DOB Confirmation**: - If pending_dob_confirmation is set (e.g., "{pending_dob_confirmation}"), check if the user confirms (e.g., "Yes, the date of birth is correct"). If confirmed, save the DOB and clear pending_dob_confirmation. If not, ask for a new DOB. 3. **Validate Input**: - Policy number: Must be non-empty. - Claimant's name: Must be non-empty. - Date of birth: Must be a valid date in any reasonable format (e.g., "2025-05-20", "May 20, 2025"). Convert to YYYY-MM-DD. If age > 80 years (based on current year 2025), set pending_dob_confirmation to the parsed DOB and ask for confirmation. - Date of treatment: Must be a valid date in any reasonable format. Convert to YYYY-MM-DD. - Reason for claim: Must be non-empty. - Amount claimed: Must be a positive number. 4. **Update Data**: Save valid fields only if not already set, unless the user provides a new value. Do not overwrite existing fields unnecessarily. Update pending_dob_confirmation as needed. 5. **Handle Missing/Invalid Fields**: List only missing fields or request corrections for invalid ones. If DOB needs confirmation, prioritize that. 6. **Generate Claim Form**: If all fields are valid (policy_number, claimant_name, dob, treatment_date, reason, amount) and pending_dob_confirmation is None, generate a markdown table claim form. Reset data afterward. Example interaction: - User: "My name is John Doe, born January 1, 1930" - Response: "The date of birth (1930-01-01) indicates an age over 80 years. Please confirm this is correct (e.g., 'Yes, the date of birth is correct') or provide a new date of birth." - User: "Yes, the date of birth is correct" - Response: "Thank you, John. I have saved your name and date of birth. Please provide your policy number, date of treatment, reason for claim, and amount claimed." Example claim form: ```markdown # Insurance Claim Form | Field | Details | |---------------------|-------------------| | Policy Number | ABC12345 | | Claimant's Name | John Doe | | Date of Birth | 1980-05-15 | | Date of Treatment | 2025-04-10 | | Reason for Claim | Knee surgery | | Amount Claimed | $5000.00 | ``` Process the user's message: "{user_message}" """ # Update current data with any previously collected fields prompt = base_prompt.format( current_data=json.dumps(claim_data, indent=2), user_message=message, pending_dob_confirmation=claim_data.get("pending_dob_confirmation", None) ) # Prepare messages for Claude messages = [] for user_input, bot_response in history: messages.append({"role": "user", "content": user_input}) messages.append({"role": "assistant", "content": bot_response}) messages.append({"role": "user", "content": prompt}) request_body = { "anthropic_version": "bedrock-2023-05-31", "max_tokens": 1000, "temperature": 0.7, "messages": messages } try: response = bedrock_runtime.invoke_model( modelId="anthropic.claude-3-5-sonnet-20240620-v1:0", body=json.dumps(request_body) ) response_body = json.loads(response['body'].read()) reply = response_body['content'][0]['text'] # Parse Claude's response to update claim_data lines = reply.split('\n') for line in lines: line = line.strip() if 'Policy Number' in line and '|' in line: claim_data['policy_number'] = line.split('|')[2].strip() elif 'Claimant\'s Name' in line and '|' in line: claim_data['claimant_name'] = line.split('|')[2].strip() elif 'Date of Birth' in line and '|' in line: dob = line.split('|')[2].strip() if is_valid_date(dob): claim_data['dob'] = dob claim_data['pending_dob_confirmation'] = None elif 'Date of Treatment' in line and '|' in line: treatment_date = line.split('|')[2].strip() if is_valid_date(treatment_date): claim_data['treatment_date'] = treatment_date elif 'Reason for Claim' in line and '|' in line: claim_data['reason'] = line.split('|')[2].strip() elif 'Amount Claimed' in line and '|' in line: amount_str = line.split('|')[2].strip().replace('$', '') try: amount = float(amount_str) if amount > 0: claim_data['amount'] = amount except ValueError: pass elif 'Please confirm this is correct' in line and 'date of birth' in line.lower(): # Extract DOB from Claude's response for confirmation dob_match = next((l for l in lines if 'Date of Birth' in l and '|' in l), None) if dob_match: dob = dob_match.split('|')[2].strip() if is_valid_date(dob): claim_data['pending_dob_confirmation'] = dob elif 'yes, the date of birth is correct' in message.lower(): if claim_data['pending_dob_confirmation']: claim_data['dob'] = claim_data['pending_dob_confirmation'] claim_data['pending_dob_confirmation'] = None # If Claude indicates the form is complete, reset claim_data if '# Insurance Claim Form' in reply: reset_claim_data() return reply except Exception as e: return f"❌ Error: {str(e)}" # Create Gradio ChatInterface iface = gr.ChatInterface( fn=chat_with_claude, title="🤖 Insurance Claim Form Assistant", description="Provide your insurance claim details (policy number, name, date of birth, date of treatment, reason for claim, amount claimed). I'll validate them and generate a claim form!", theme="soft", ) if __name__ == "__main__": iface.launch()