|
|
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 |
|
|
import logging |
|
|
|
|
|
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. |
|
|
""" |
|
|
try: |
|
|
logger.info("Received coding request") |
|
|
|
|
|
|
|
|
provider_notes = request.provider_notes |
|
|
|
|
|
if not provider_notes or len(provider_notes.strip()) < 10: |
|
|
raise HTTPException( |
|
|
status_code=400, |
|
|
detail="Provider notes must be at least 10 characters long" |
|
|
) |
|
|
|
|
|
|
|
|
result = await groq_service.analyze_provider_notes(provider_notes) |
|
|
|
|
|
logger.info("Successfully processed coding request") |
|
|
|
|
|
|
|
|
return CodingResponse( |
|
|
cpt_codes=result.get("CPT", []), |
|
|
cpt_explanation=result.get("CPT_explanation", ""), |
|
|
icd_codes=result.get("ICD", []), |
|
|
icd_explanation=result.get("ICD_explanation", "") |
|
|
) |
|
|
|
|
|
except HTTPException: |
|
|
raise |
|
|
except Exception as e: |
|
|
logger.error(f"Error in analyze_provider_notes: {str(e)}") |
|
|
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 TXT file containing provider notes and extract ICD-10 and CPT codes |
|
|
|
|
|
This endpoint: |
|
|
1. Extracts text from uploaded TXT file |
|
|
2. Automatically detects and removes patient personal information (PII) |
|
|
3. Processes sanitized text through LLM |
|
|
4. Returns ICD-10 and CPT codes |
|
|
|
|
|
Args: |
|
|
file: TXT file containing provider notes |
|
|
|
|
|
Returns: |
|
|
FileUploadResponse with codes, explanations, and PII removal info |
|
|
""" |
|
|
try: |
|
|
logger.info(f"📁 Received file upload request: {file.filename}") |
|
|
|
|
|
|
|
|
extraction_result = await file_service.extract_text_from_file( |
|
|
file=file, |
|
|
remove_pii=True |
|
|
) |
|
|
|
|
|
extracted_text = extraction_result["text"] |
|
|
filename = extraction_result["filename"] |
|
|
text_length = extraction_result["text_length"] |
|
|
pii_info = extraction_result["pii_info"] |
|
|
|
|
|
logger.info(f"✅ Extracted {text_length} characters from {filename}") |
|
|
|
|
|
if pii_info["pii_removed"]: |
|
|
logger.info(f"🔒 Removed {pii_info['pii_count']} PII entities before processing") |
|
|
|
|
|
|
|
|
coding_result = await groq_service.analyze_provider_notes(extracted_text) |
|
|
|
|
|
logger.info(f"✅ Successfully processed file: {filename}") |
|
|
|
|
|
|
|
|
return FileUploadResponse( |
|
|
success=True, |
|
|
filename=filename, |
|
|
extracted_text_length=text_length, |
|
|
pii_removed=pii_info["pii_removed"], |
|
|
pii_count=pii_info["pii_count"], |
|
|
cpt_codes=coding_result.get("CPT", []), |
|
|
cpt_explanation=coding_result.get("CPT_explanation", ""), |
|
|
icd_codes=coding_result.get("ICD", []), |
|
|
icd_explanation=coding_result.get("ICD_explanation", "") |
|
|
) |
|
|
|
|
|
except HTTPException: |
|
|
raise |
|
|
except Exception as e: |
|
|
logger.error(f"❌ Error in upload_provider_notes_file: {str(e)}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Error processing uploaded file: {str(e)}" |
|
|
) |