File size: 4,151 Bytes
480f467 a8f12f6 764e30e 56edde7 a8f12f6 56edde7 a8f12f6 56edde7 a8f12f6 56edde7 480f467 56edde7 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 3cbb4d9 480f467 a8f12f6 480f467 56edde7 480f467 a8f12f6 56edde7 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 764e30e a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 764e30e a8f12f6 480f467 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
import logging
from fastapi import APIRouter, HTTPException, UploadFile, File
from models.request_models import ProviderNotesRequest
from models.response_models import CodingResponse, FileUploadResponse
from services.groq_service import groq_service
from services.file_service import file_service
router = APIRouter()
logger = logging.getLogger(__name__)
@router.post("/coding", response_model=CodingResponse)
async def analyze_provider_notes(request: ProviderNotesRequest):
"""
Analyze provider notes and extract ICD-10 and CPT codes
This endpoint accepts provider notes as text input and returns:
- ICD-10 diagnostic codes with explanations
- CPT procedure codes with explanations
- Overall encounter summary
"""
try:
logger.info(f"📥 Received coding request (notes length: {len(request.provider_notes)})")
# Validate input
if not request.provider_notes or len(request.provider_notes.strip()) < 10:
raise HTTPException(
status_code=400,
detail="Provider notes must be at least 10 characters long"
)
# Analyze with Groq
result = groq_service.analyze_provider_notes(request.provider_notes)
logger.info(f"✅ Analysis complete: {len(result.get('icd_codes', []))} ICD codes, {len(result.get('cpt_codes', []))} CPT codes")
return result
except HTTPException:
raise
except ValueError as e:
logger.error(f"❌ Validation error: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"❌ Error processing request: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error processing request: {str(e)}")
@router.post("/upload-file", response_model=FileUploadResponse)
async def upload_provider_notes_file(file: UploadFile = File(...)):
"""
Upload a provider notes file (.txt), remove PII, and analyze
Returns:
- File processing info (PII removal stats)
- ICD-10 codes with explanations
- CPT codes with explanations
- Overall summary
"""
try:
logger.info(f"📤 Received file upload: {file.filename}")
# Validate file type
if not file.filename.endswith('.txt'):
raise HTTPException(
status_code=400,
detail="Only .txt files are allowed"
)
# Read file content
content = await file.read()
text = content.decode('utf-8')
logger.info(f"📄 File read successfully (length: {len(text)})")
# Remove PII
try:
cleaned_text, pii_count = file_service.remove_pii(text)
logger.info(f"🔒 PII removal complete: {pii_count} entities removed")
except Exception as pii_error:
logger.error(f"⚠️ PII removal failed: {str(pii_error)}")
# Continue without PII removal if it fails
cleaned_text = text
pii_count = 0
# Analyze with Groq
result = groq_service.analyze_provider_notes(cleaned_text)
# Combine results
response = {
"success": True,
"filename": file.filename,
"extracted_text_length": len(text),
"pii_removed": pii_count > 0,
"pii_count": pii_count,
"icd_codes": result.get("icd_codes", []),
"cpt_codes": result.get("cpt_codes", []),
"overall_summary": result.get("overall_summary", "")
}
logger.info(f"✅ File processing complete")
return response
except HTTPException:
raise
except UnicodeDecodeError:
logger.error("❌ File encoding error")
raise HTTPException(status_code=400, detail="File must be UTF-8 encoded text")
except Exception as e:
logger.error(f"❌ Error processing uploaded file: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Error processing uploaded file: {str(e)}") |