garvitcpp commited on
Commit
09410eb
·
verified ·
1 Parent(s): c09ce8d

Upload 29 files

Browse files
.gitignore ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .idea
2
+ .ipynb_checkpoints
3
+ .mypy_cache
4
+ .vscode
5
+ __pycache__
6
+ .pytest_cache
7
+ htmlcov
8
+ dist
9
+ site
10
+ .coverage*
11
+ coverage.xml
12
+ .netlify
13
+ test.db
14
+ log.txt
15
+ Pipfile.lock
16
+ env3.*
17
+ env
18
+ docs_build
19
+ site_build
20
+ venv
21
+ docs.zip
22
+ archive.zip
23
+
24
+ # vim temporary files
25
+ *~
26
+ .*.sw?
27
+ .cache
28
+
29
+ # macOS
30
+ .DS_Store
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /code
4
+
5
+ # Copy requirements first to leverage Docker cache
6
+ COPY requirements.txt .
7
+
8
+ # Install dependencies
9
+ RUN pip install --no-cache-dir -r requirements.txt && \
10
+ pip install --no-cache-dir google-generativeai
11
+
12
+ # Copy the rest of the application
13
+ COPY . .
14
+
15
+ # Command to run the application
16
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
app/__init__.py ADDED
File without changes
app/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (138 Bytes). View file
 
app/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (154 Bytes). View file
 
app/api/__init__.py ADDED
File without changes
app/api/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (142 Bytes). View file
 
app/api/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (158 Bytes). View file
 
app/api/__pycache__/models.cpython-310.pyc ADDED
Binary file (1.18 kB). View file
 
app/api/__pycache__/routes.cpython-310.pyc ADDED
Binary file (1.23 kB). View file
 
app/api/__pycache__/routes.cpython-311.pyc ADDED
Binary file (2.18 kB). View file
 
app/api/models.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app/api/models.py
2
+ from typing import List, Optional
3
+ from pydantic import BaseModel, Field
4
+
5
+ class TraditionalRequest(BaseModel):
6
+ symptoms: List[str] = Field(..., min_items=1, description="List of symptoms")
7
+ age: int = Field(..., gt=0, lt=121)
8
+ gender: str
9
+ duration: str
10
+ additional_info: Optional[str] = None
11
+
12
+ class BodyBasedRequest(BaseModel):
13
+ age: int = Field(..., gt=0, lt=121)
14
+ gender: str
15
+ body_parts: List[str] = Field(..., min_items=1, description="List of affected body parts")
16
+ symptom_types: List[str] = Field(..., min_items=1, description="List of symptom types")
17
+ severity: str
18
+ duration: str
19
+ description: str = Field(..., min_length=10, max_length=500)
app/api/routes.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException
2
+ from ..core.analyzer import SymptomAnalyzer
3
+ from .models import TraditionalRequest, BodyBasedRequest
4
+
5
+ router = APIRouter()
6
+ analyzer = SymptomAnalyzer()
7
+
8
+ @router.post("/analyze/traditional")
9
+ async def analyze_traditional(request: TraditionalRequest):
10
+ try:
11
+ result = await analyzer.analyze_traditional(
12
+ request.symptoms,
13
+ request.age,
14
+ request.gender,
15
+ request.duration
16
+ )
17
+ return result
18
+ except Exception as e:
19
+ raise HTTPException(status_code=500, detail=str(e))
20
+
21
+ @router.post("/analyze/body-based")
22
+ async def analyze_body_based(request: BodyBasedRequest):
23
+ try:
24
+ data = request.dict()
25
+ result = await analyzer.analyze_body_based(data)
26
+ return result
27
+ except Exception as e:
28
+ raise HTTPException(status_code=500, detail=str(e))
29
+
30
+ @router.get("/health")
31
+ async def health_check():
32
+ return {"status": "healthy", "message": "Server is running"}
app/core/__init__.py ADDED
File without changes
app/core/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (143 Bytes). View file
 
app/core/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (159 Bytes). View file
 
app/core/__pycache__/analyzer.cpython-310.pyc ADDED
Binary file (2 kB). View file
 
app/core/__pycache__/analyzer.cpython-311.pyc ADDED
Binary file (3.8 kB). View file
 
app/core/__pycache__/config.cpython-310.pyc ADDED
Binary file (528 Bytes). View file
 
app/core/analyzer.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, List
2
+ import json
3
+ import google.generativeai as genai
4
+ from fastapi import HTTPException
5
+ from ..utils.prompt_templates import generate_traditional_prompt, generate_body_based_prompt
6
+
7
+ class SymptomAnalyzer:
8
+ def __init__(self):
9
+ self.model = genai.GenerativeModel('gemini-1.5-flash')
10
+
11
+ async def analyze_traditional(self, symptoms: List[str], age: int, gender: str, duration: str) -> Dict:
12
+ try:
13
+ prompt = generate_traditional_prompt(symptoms, age, gender, duration)
14
+ response = self.model.generate_content(prompt)
15
+
16
+ try:
17
+ parsed_response = json.loads(response.text)
18
+ return parsed_response
19
+ except json.JSONDecodeError as e:
20
+ cleaned_response = response.text.strip().strip('`').strip('json')
21
+ try:
22
+ parsed_response = json.loads(cleaned_response)
23
+ return parsed_response
24
+ except json.JSONDecodeError:
25
+ raise HTTPException(
26
+ status_code=500,
27
+ detail="Failed to parse response into valid JSON"
28
+ )
29
+
30
+ except Exception as e:
31
+ raise HTTPException(status_code=500, detail=f"Analysis error: {str(e)}")
32
+
33
+ async def analyze_body_based(self, data: Dict) -> Dict:
34
+ try:
35
+ prompt = generate_body_based_prompt(data)
36
+ response = self.model.generate_content(prompt)
37
+
38
+ try:
39
+ parsed_response = json.loads(response.text)
40
+ return parsed_response
41
+ except json.JSONDecodeError as e:
42
+ cleaned_response = response.text.strip().strip('`').strip('json')
43
+ try:
44
+ parsed_response = json.loads(cleaned_response)
45
+ return parsed_response
46
+ except json.JSONDecodeError:
47
+ raise HTTPException(
48
+ status_code=500,
49
+ detail="Failed to parse response into valid JSON"
50
+ )
51
+
52
+ except Exception as e:
53
+ raise HTTPException(status_code=500, detail=f"Analysis error: {str(e)}")
app/core/config.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app/core/config.py
2
+ import os
3
+ import google.generativeai as genai
4
+ from dotenv import load_dotenv
5
+
6
+ def init_config():
7
+ # Load environment variables
8
+ load_dotenv()
9
+
10
+ # Get API key
11
+ api_key = os.getenv('GEMINI_API_KEY')
12
+
13
+ if not api_key:
14
+ raise ValueError("GEMINI_API_KEY not found in environment variables")
15
+
16
+ # Configure Gemini
17
+ genai.configure(api_key=api_key)
app/utils/__init__.py ADDED
File without changes
app/utils/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (144 Bytes). View file
 
app/utils/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (160 Bytes). View file
 
app/utils/__pycache__/prompt_templates.cpython-310.pyc ADDED
Binary file (7.15 kB). View file
 
app/utils/__pycache__/prompt_templates.cpython-311.pyc ADDED
Binary file (7.66 kB). View file
 
app/utils/prompt_templates.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+
3
+ def generate_traditional_prompt(symptoms: List[str], age: int, gender: str, duration: str) -> str:
4
+ return f"""
5
+ As a medical information assistant, analyze these symptoms and provide a response in valid JSON format.
6
+
7
+ Patient Information:
8
+ - Age: {age}
9
+ - Gender: {gender}
10
+ - Duration of Symptoms: {duration}
11
+ - Reported Symptoms: {', '.join(symptoms)}
12
+
13
+ Format your response as a valid JSON object with the following structure.
14
+ Ensure all values are properly quoted strings or arrays and the JSON is properly formatted:
15
+
16
+ {{
17
+ "initial_assessment": {{
18
+ "summary": "string",
19
+ "primary_symptoms": ["string"],
20
+ "duration_analysis": "string"
21
+ }},
22
+ "possible_conditions": {{
23
+ "primary_possibilities": [
24
+ {{
25
+ "name": "string",
26
+ "likelihood": "string",
27
+ "description": "string",
28
+ "typical_duration": "string",
29
+ "complications": ["string"]
30
+ }}
31
+ ],
32
+ "differential_diagnoses": ["string"]
33
+ }},
34
+ "severity_indicators": {{
35
+ "current_level": "string",
36
+ "explanation": "string",
37
+ "warning_signs": ["string"],
38
+ "emergency_indicators": ["string"]
39
+ }},
40
+ "recommendations": {{
41
+ "immediate_steps": ["string"],
42
+ "home_care": ["string"],
43
+ "medications": {{
44
+ "over_the_counter": ["string"],
45
+ "precautions": ["string"]
46
+ }},
47
+ "lifestyle_changes": ["string"]
48
+ }},
49
+ "when_to_seek_care": {{
50
+ "emergency_care": ["string"],
51
+ "urgent_care": ["string"],
52
+ "routine_care": ["string"]
53
+ }},
54
+ "prevention": {{
55
+ "immediate_actions": ["string"],
56
+ "long_term_strategies": ["string"]
57
+ }},
58
+ "follow_up": {{
59
+ "monitoring": ["string"],
60
+ "timeline": "string",
61
+ "documentation": ["string"]
62
+ }},
63
+ "education": {{
64
+ "condition_info": ["string"],
65
+ "myths_facts": ["string"],
66
+ "additional_resources": ["string"]
67
+ }},
68
+ "disclaimers": {{
69
+ "medical_advice": "string",
70
+ "limitations": ["string"],
71
+ "emergency_notice": "string"
72
+ }}
73
+ }}
74
+
75
+ Return ONLY the JSON object with no additional text or formatting.
76
+ """
77
+
78
+ def generate_body_based_prompt(data: dict) -> str:
79
+ body_parts = ', '.join(data['body_parts'])
80
+ symptom_types = ', '.join(data['symptom_types'])
81
+
82
+ return f"""
83
+ As a medical information assistant, analyze these multiple body-related symptoms and provide a response in valid JSON format.
84
+
85
+ Patient Information:
86
+ - Age: {data['age']}
87
+ - Gender: {data['gender']}
88
+ - Affected Areas: {body_parts}
89
+ - Symptom Types: {symptom_types}
90
+ - Severity: {data['severity']}
91
+ - Duration: {data['duration']}
92
+ - Description: {data['description']}
93
+
94
+ Format your response as a valid JSON object with the following structure.
95
+ Ensure all values are properly quoted strings or arrays and the JSON is properly formatted:
96
+
97
+ {{
98
+ "symptom_analysis": {{
99
+ "locations": [
100
+ {{
101
+ "area": "string",
102
+ "involved_structures": ["string"],
103
+ "radiation_patterns": ["string"],
104
+ "specific_symptoms": ["string"]
105
+ }}
106
+ ],
107
+ "characteristics": {{
108
+ "primary_symptoms": ["string"],
109
+ "quality": ["string"],
110
+ "severity": "string",
111
+ "pattern": "string",
112
+ "aggravating_factors": ["string"],
113
+ "relieving_factors": ["string"]
114
+ }}
115
+ }},
116
+ "clinical_considerations": {{
117
+ "possible_conditions": [
118
+ {{
119
+ "name": "string",
120
+ "likelihood": "string",
121
+ "description": "string",
122
+ "typical_progression": "string",
123
+ "affected_areas": ["string"]
124
+ }}
125
+ ],
126
+ "risk_factors": ["string"],
127
+ "red_flags": ["string"]
128
+ }},
129
+ "diagnostic_approach": {{
130
+ "key_questions": [
131
+ {{
132
+ "question": "string",
133
+ "reason": "string",
134
+ "significance": "string"
135
+ }}
136
+ ],
137
+ "physical_findings": ["string"],
138
+ "suggested_monitoring": ["string"]
139
+ }},
140
+ "management_recommendations": {{
141
+ "immediate_care": {{
142
+ "actions": ["string"],
143
+ "restrictions": ["string"],
144
+ "positioning": "string"
145
+ }},
146
+ "pain_management": {{
147
+ "medications": ["string"],
148
+ "physical_measures": ["string"],
149
+ "precautions": ["string"]
150
+ }},
151
+ "activity_modification": {{
152
+ "restricted_activities": ["string"],
153
+ "permitted_activities": ["string"],
154
+ "gradual_progression": "string"
155
+ }}
156
+ }},
157
+ "care_guidance": {{
158
+ "self_care": ["string"],
159
+ "medical_care": {{
160
+ "when_to_seek": ["string"],
161
+ "type_of_care": "string",
162
+ "urgency": "string"
163
+ }}
164
+ }},
165
+ "prevention_education": {{
166
+ "recurrence_prevention": ["string"],
167
+ "lifestyle_modifications": ["string"],
168
+ "ergonomic_advice": ["string"]
169
+ }},
170
+ "prognosis": {{
171
+ "expected_course": "string",
172
+ "recovery_timeline": "string",
173
+ "complications": ["string"]
174
+ }},
175
+ "disclaimers": {{
176
+ "medical_advice": "string",
177
+ "limitations": ["string"],
178
+ "emergency_notice": "string"
179
+ }}
180
+ }}
181
+
182
+ Return ONLY the JSON object with no additional text or formatting.
183
+ """
main.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+ from fastapi import FastAPI
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from app.core.config import init_config
5
+ from app.api.routes import router
6
+
7
+ # Initialize configuration before creating the app
8
+ init_config()
9
+
10
+ app = FastAPI(
11
+ title="Symptom Analysis System",
12
+ description="AI-powered symptom analysis system",
13
+ version="1.0.0"
14
+ )
15
+
16
+ app.add_middleware(
17
+ CORSMiddleware,
18
+ allow_origins=["*"],
19
+ allow_credentials=True,
20
+ allow_methods=["*"],
21
+ allow_headers=["*"],
22
+ )
23
+
24
+ app.include_router(router)
25
+
26
+ if __name__ == "__main__":
27
+ import uvicorn
28
+ uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
requirements.txt ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ annotated-types==0.7.0
2
+ anyio==4.7.0
3
+ click==8.1.7
4
+ colorama==0.4.6
5
+ fastapi==0.115.6
6
+ h11==0.14.0
7
+ idna==3.10
8
+ joblib==1.4.2
9
+ numpy==2.2.0
10
+ pandas==2.2.3
11
+ pydantic==2.10.3
12
+ pydantic_core==2.27.1
13
+ python-dateutil==2.9.0.post0
14
+ python-multipart==0.0.19
15
+ pytz==2024.2
16
+ scikit-learn==1.0.2
17
+ scipy==1.14.1
18
+ six==1.17.0
19
+ sniffio==1.3.1
20
+ starlette==0.41.3
21
+ threadpoolctl==3.5.0
22
+ typing_extensions==4.12.2
23
+ tzdata==2024.2
24
+ uvicorn==0.32.1