File size: 7,875 Bytes
6dc9d46
 
 
 
 
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
 
 
 
 
 
 
 
9659593
6dc9d46
 
 
 
 
9659593
6dc9d46
 
 
 
 
 
 
 
 
 
 
9659593
6dc9d46
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
9659593
6dc9d46
696f787
6dc9d46
 
9659593
696f787
6dc9d46
 
 
 
 
 
 
9659593
 
6dc9d46
696f787
6dc9d46
 
 
 
 
 
 
9659593
 
6dc9d46
696f787
6dc9d46
 
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
 
 
 
9659593
6dc9d46
696f787
6dc9d46
696f787
6dc9d46
 
 
 
 
696f787
9659593
 
 
6dc9d46
 
 
 
 
 
9659593
6dc9d46
 
 
 
 
9659593
6dc9d46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9659593
6dc9d46
 
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
9659593
6dc9d46
696f787
6dc9d46
 
 
 
 
 
 
9659593
 
6dc9d46
696f787
6dc9d46
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
 
 
 
9659593
6dc9d46
696f787
6dc9d46
696f787
6dc9d46
 
 
 
 
696f787
9659593
 
 
6dc9d46
 
 
 
 
 
9659593
6dc9d46
 
 
 
9659593
6dc9d46
 
 
 
9659593
6dc9d46
 
696f787
6dc9d46
 
696f787
6dc9d46
 
 
9659593
6dc9d46
696f787
6dc9d46
 
 
 
 
 
 
 
aefac4f
 
6dc9d46
aefac4f
9659593
6dc9d46
696f787
9659593
696f787
6dc9d46
 
 
 
 
 
 
 
9659593
 
6dc9d46
696f787
6dc9d46
 
 
 
 
 
9659593
6dc9d46
696f787
6dc9d46
696f787
6dc9d46
 
 
9659593
 
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
"""
Analysis Endpoints
Natural language and structured biomarker analysis
"""

import os

from fastapi import APIRouter, HTTPException, status

from app.models.schemas import AnalysisResponse, NaturalAnalysisRequest, StructuredAnalysisRequest
from app.services.extraction import extract_biomarkers, predict_disease_simple
from app.services.ragbot import get_ragbot_service

router = APIRouter(prefix="/api/v1", tags=["analysis"])


@router.post("/analyze/natural", response_model=AnalysisResponse)
async def analyze_natural(request: NaturalAnalysisRequest):
    """
    Analyze biomarkers from natural language input.

    **Flow:**
    1. Extract biomarkers from natural language using LLM
    2. Predict disease using rule-based or ML model
    3. Run complete RAG workflow analysis
    4. Return comprehensive results

    **Example request:**
    ```json
    {
      "message": "My glucose is 185, HbA1c is 8.2 and cholesterol is 210",
      "patient_context": {
        "age": 52,
        "gender": "male",
        "bmi": 31.2
      }
    }
    ```

    Returns full detailed analysis with all agent outputs, citations, recommendations.
    """

    # Get services
    ragbot_service = get_ragbot_service()

    if not ragbot_service.is_ready():
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="RagBot service not initialized. Please try again in a moment.",
        )

    # Extract biomarkers from natural language
    ollama_base_url = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
    biomarkers, extracted_context, error = extract_biomarkers(request.message, ollama_base_url=ollama_base_url)

    if error:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error_code": "EXTRACTION_FAILED",
                "message": error,
                "input_received": request.message[:100],
                "suggestion": "Try: 'My glucose is 140 and HbA1c is 7.5'",
            },
        )

    if not biomarkers:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error_code": "NO_BIOMARKERS_FOUND",
                "message": "Could not extract any biomarkers from your message",
                "input_received": request.message[:100],
                "suggestion": "Include specific biomarker values like 'glucose is 140'",
            },
        )

    # Merge extracted context with request context
    patient_context = request.patient_context.model_dump() if request.patient_context else {}
    patient_context.update(extracted_context)

    # Predict disease (simple rule-based for now)
    model_prediction = predict_disease_simple(biomarkers)

    try:
        # Run full analysis
        response = ragbot_service.analyze(
            biomarkers=biomarkers,
            patient_context=patient_context,
            model_prediction=model_prediction,
            extracted_biomarkers=biomarkers,  # Keep original extraction
        )

        return response

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail={
                "error_code": "ANALYSIS_FAILED",
                "message": f"Analysis workflow failed: {e!s}",
                "biomarkers_received": biomarkers,
            },
        ) from e


@router.post("/analyze/structured", response_model=AnalysisResponse)
async def analyze_structured(request: StructuredAnalysisRequest):
    """
    Analyze biomarkers from structured input (skip extraction).

    **Flow:**
    1. Use provided biomarker dictionary directly
    2. Predict disease using rule-based or ML model
    3. Run complete RAG workflow analysis
    4. Return comprehensive results

    **Example request:**
    ```json
    {
      "biomarkers": {
        "Glucose": 185.0,
        "HbA1c": 8.2,
        "Cholesterol": 210.0,
        "Triglycerides": 210.0,
        "HDL": 38.0
      },
      "patient_context": {
        "age": 52,
        "gender": "male",
        "bmi": 31.2
      }
    }
    ```

    Use this endpoint when you already have structured biomarker data.
    Returns full detailed analysis with all agent outputs, citations, recommendations.
    """

    # Get services
    ragbot_service = get_ragbot_service()

    if not ragbot_service.is_ready():
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="RagBot service not initialized. Please try again in a moment.",
        )

    # Validate biomarkers
    if not request.biomarkers:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={
                "error_code": "NO_BIOMARKERS",
                "message": "Biomarkers dictionary cannot be empty",
                "suggestion": "Provide at least one biomarker with a numeric value",
            },
        )

    # Patient context
    patient_context = request.patient_context.model_dump() if request.patient_context else {}

    # Predict disease
    model_prediction = predict_disease_simple(request.biomarkers)

    try:
        # Run full analysis
        response = ragbot_service.analyze(
            biomarkers=request.biomarkers,
            patient_context=patient_context,
            model_prediction=model_prediction,
            extracted_biomarkers=None,  # No extraction for structured input
        )

        return response

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail={
                "error_code": "ANALYSIS_FAILED",
                "message": f"Analysis workflow failed: {e!s}",
                "biomarkers_received": request.biomarkers,
            },
        ) from e


@router.get("/example", response_model=AnalysisResponse)
async def get_example():
    """
    Get example diabetes case analysis.

    **Pre-run example case:**
    - 52-year-old male patient
    - Elevated glucose and HbA1c
    - Type 2 Diabetes prediction

    Useful for:
    - Testing API integration
    - Understanding response format
    - Demo purposes

    Same as CLI chatbot 'example' command.
    """

    # Get services
    ragbot_service = get_ragbot_service()

    if not ragbot_service.is_ready():
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="RagBot service not initialized. Please try again in a moment.",
        )

    # Example biomarkers (Type 2 Diabetes patient)
    biomarkers = {
        "Glucose": 185.0,
        "HbA1c": 8.2,
        "Hemoglobin": 13.5,
        "Platelets": 220000.0,
        "Cholesterol": 235.0,
        "Triglycerides": 210.0,
        "HDL Cholesterol": 38.0,
        "LDL Cholesterol": 165.0,
        "BMI": 31.2,
        "Systolic Blood Pressure": 142.0,
        "Diastolic Blood Pressure": 88.0,
    }

    patient_context = {"age": 52, "gender": "male", "bmi": 31.2, "patient_id": "EXAMPLE-001"}

    model_prediction = {
        "disease": "Diabetes",
        "confidence": 0.87,
        "probabilities": {
            "Diabetes": 0.87,
            "Heart Disease": 0.08,
            "Anemia": 0.03,
            "Thalassemia": 0.01,
            "Thrombocytopenia": 0.01,
        },
    }

    try:
        # Run analysis
        response = ragbot_service.analyze(
            biomarkers=biomarkers,
            patient_context=patient_context,
            model_prediction=model_prediction,
            extracted_biomarkers=None,
        )

        return response

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail={"error_code": "EXAMPLE_FAILED", "message": f"Example analysis failed: {e!s}"},
        ) from e