refactor estimation service to use structured agent
This commit is contained in:
parent
47cc1541ed
commit
96421b264c
7 changed files with 316 additions and 361 deletions
|
|
@ -4,7 +4,7 @@ import httpx
|
|||
|
||||
from . import models
|
||||
from ...services.chat_service import chat_service
|
||||
from ...services.estimation_service import run_underwriting
|
||||
from ...services.estimation_service import estimation_service
|
||||
from ...config import settings
|
||||
|
||||
router = APIRouter()
|
||||
|
|
@ -26,6 +26,7 @@ async def insurance_chat(request: models.InsuranceChatRequest):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
raise HTTPException(status_code=500, detail=f"Error processing chat request: {str(e)}")
|
||||
|
||||
@router.post("/estimation", response_model=models.EstimationResponse)
|
||||
|
|
@ -39,104 +40,8 @@ async def estimate(request: models.EstimationRequest):
|
|||
detail="Missing required applicants or plans"
|
||||
)
|
||||
|
||||
# Convert request to the format expected by run_underwriting
|
||||
applicants_dict = []
|
||||
for applicant in request.applicants:
|
||||
applicants_dict.append({
|
||||
"applicant": applicant.applicant,
|
||||
"firstName": applicant.firstName,
|
||||
"lastName": applicant.lastName,
|
||||
"midName": applicant.midName,
|
||||
"phone": applicant.phone,
|
||||
"gender": applicant.gender,
|
||||
"dob": applicant.dob.strftime("%d/%m/%Y"),
|
||||
"nicotine": applicant.nicotine,
|
||||
"weight": applicant.weight,
|
||||
"heightFt": applicant.heightFt,
|
||||
"heightIn": applicant.heightIn
|
||||
})
|
||||
|
||||
phq_dict = {
|
||||
"treatment": request.phq.treatment,
|
||||
"invalid": request.phq.invalid,
|
||||
"pregnancy": request.phq.pregnancy,
|
||||
"effectiveDate": request.phq.effectiveDate.strftime("%d/%m/%Y"),
|
||||
"disclaimer": request.phq.disclaimer,
|
||||
"signature": request.phq.signature,
|
||||
"medications": [
|
||||
{
|
||||
"applicant": med.applicant,
|
||||
"name": med.name,
|
||||
"rxcui": med.rxcui,
|
||||
"dosage": med.dosage,
|
||||
"frequency": med.frequency,
|
||||
"description": med.description
|
||||
} for med in request.phq.medications
|
||||
],
|
||||
"issues": [
|
||||
{
|
||||
"key": issue.key,
|
||||
"details": [
|
||||
{
|
||||
"key": detail.key,
|
||||
"description": detail.description
|
||||
} for detail in issue.details
|
||||
]
|
||||
} for issue in request.phq.issues
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"key": condition.key,
|
||||
"description": condition.description
|
||||
} for condition in request.phq.conditions
|
||||
]
|
||||
}
|
||||
|
||||
plans_dict = [
|
||||
{
|
||||
"id": plan.id,
|
||||
"coverage": plan.coverage,
|
||||
"tier": plan.tier
|
||||
} for plan in request.plans
|
||||
]
|
||||
|
||||
# Step 1: Run estimation
|
||||
underwriting_result = run_underwriting(applicants_dict, phq_dict, plans_dict)
|
||||
|
||||
# Step 2: Check if DTQ → reject application
|
||||
if underwriting_result["combined"].get("dtq"):
|
||||
# For DTQ cases, call external reject API and return rejected status
|
||||
if request.uid:
|
||||
reject_response = await reject_application(request.uid)
|
||||
return models.EstimationResponse(
|
||||
status="rejected",
|
||||
details=models.EstimationDetails(
|
||||
dtq=True,
|
||||
reason="Declined due to high-risk conditions (DTQ triggered).",
|
||||
tier=int(underwriting_result["combined"]["tier"]),
|
||||
total_price=underwriting_result["combined"]["total_price"]
|
||||
),
|
||||
results=[
|
||||
models.EstimationResult(
|
||||
name=result["name"],
|
||||
applicant_type=result["applicant_type"],
|
||||
age=result["age"] or 0,
|
||||
bmi=result["bmi"] or 0.0,
|
||||
tier=int(result["tier"]),
|
||||
rx_spend=result["rx_spend"],
|
||||
message=result["message"]
|
||||
) for result in underwriting_result["results"]
|
||||
]
|
||||
)
|
||||
|
||||
# Step 3: Else → assign tier and submit to external API
|
||||
final_tier = underwriting_result["combined"]["tier"]
|
||||
plans = request.plans.copy()
|
||||
if plans:
|
||||
plans[0].tier = f"tier_{str(final_tier).replace('.', '_')}"
|
||||
|
||||
# Assemble external payload
|
||||
submission_payload = {
|
||||
# Convert request to the format expected by the estimation service
|
||||
request_data = {
|
||||
"applicants": [
|
||||
{
|
||||
"applicant": applicant.applicant,
|
||||
|
|
@ -157,7 +62,7 @@ async def estimate(request: models.EstimationRequest):
|
|||
"id": plan.id,
|
||||
"coverage": plan.coverage,
|
||||
"tier": plan.tier
|
||||
} for plan in plans
|
||||
} for plan in request.plans
|
||||
],
|
||||
"phq": {
|
||||
"treatment": request.phq.treatment,
|
||||
|
|
@ -204,27 +109,42 @@ async def estimate(request: models.EstimationRequest):
|
|||
}
|
||||
}
|
||||
|
||||
submit_response = await submit_application(submission_payload)
|
||||
# Call the TALESTORM API for estimation
|
||||
estimation_result = await estimation_service.estimate_insurance(request_data)
|
||||
|
||||
# Handle the response from TALESTORM API
|
||||
if estimation_result.get("status") == "error":
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=estimation_result.get("details", {}).get("reason", "Estimation service error")
|
||||
)
|
||||
|
||||
# Extract details and results from the TALESTORM response
|
||||
details = estimation_result.get("details", {})
|
||||
results = estimation_result.get("results", [])
|
||||
|
||||
# Convert results to the expected format
|
||||
estimation_results = []
|
||||
for result in results:
|
||||
estimation_results.append(models.EstimationResult(
|
||||
name=result.get("name", "Unknown"),
|
||||
applicant_type=result.get("applicant_type", "Unknown"),
|
||||
age=result.get("age", 0),
|
||||
bmi=result.get("bmi", 0.0),
|
||||
tier=result.get("tier", 4),
|
||||
rx_spend=result.get("rx_spend", 0.0),
|
||||
message=result.get("message", "")
|
||||
))
|
||||
|
||||
return models.EstimationResponse(
|
||||
status="accepted",
|
||||
status=estimation_result.get("status", "accepted"),
|
||||
details=models.EstimationDetails(
|
||||
dtq=False,
|
||||
reason=underwriting_result["combined"]["message"],
|
||||
tier=int(underwriting_result["combined"]["tier"]),
|
||||
total_price=underwriting_result["combined"]["total_price"]
|
||||
dtq=details.get("dtq", False),
|
||||
reason=details.get("reason", ""),
|
||||
tier=details.get("tier", 4),
|
||||
total_price=details.get("total_price", 0.0)
|
||||
),
|
||||
results=[
|
||||
models.EstimationResult(
|
||||
name=result["name"],
|
||||
applicant_type=result["applicant_type"],
|
||||
age=result["age"] or 0,
|
||||
bmi=result["bmi"] or 0.0,
|
||||
tier=int(result["tier"]),
|
||||
rx_spend=result["rx_spend"],
|
||||
message=result["message"]
|
||||
) for result in underwriting_result["results"]
|
||||
]
|
||||
results=estimation_results
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
|
|
@ -236,23 +156,7 @@ async def estimate(request: models.EstimationRequest):
|
|||
)
|
||||
|
||||
|
||||
async def reject_application(uid: str) -> Dict[str, Any]:
|
||||
"""Reject application via external API"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
f"{settings.INSURANCE_API_BASE_URL}/applications/reject",
|
||||
json={"applicationId": uid}
|
||||
)
|
||||
return response.json() if response.status_code == 200 else {"error": "Failed to reject application"}
|
||||
|
||||
async def submit_application(application_payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Submit application via external API"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
f"{settings.INSURANCE_API_BASE_URL}/applications/submit",
|
||||
json=application_payload
|
||||
)
|
||||
return response.json() if response.status_code == 200 else {"error": "Failed to submit application"}
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue