File size: 3,748 Bytes
480f467 a8f12f6 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 fd20bd2 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 a8f12f6 480f467 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 |
import logging
from fastapi import APIRouter, HTTPException, UploadFile, File
from models.request_models import ProviderNotesRequest, FileUploadResponse
from models.response_models import CodingResponse
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
cleaned_text, pii_count = file_service.remove_pii(text)
logger.info(f"🔒 PII removal complete: {pii_count} entities removed")
# 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 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)}") |