Skip to content

Commit 2d80d45

Browse files
-- add the new file for fastAPI
1 parent 2e55995 commit 2d80d45

File tree

16 files changed

+579
-0
lines changed

16 files changed

+579
-0
lines changed

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM python:3.11-slim
2+
3+
WORKDIR /app
4+
5+
# Copy requirements first to leverage Docker cache
6+
COPY requirements.txt .
7+
RUN pip install --no-cache-dir -r requirements.txt
8+
9+
# Copy the rest of the application
10+
COPY . .
11+
12+
# Command to run the application
13+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# DocGPT
2+

app/schemas/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Schema package initialization.
3+
"""

app/schemas/health.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from pydantic import BaseModel
2+
from typing import Dict, Literal
3+
4+
class HealthCheck(BaseModel):
5+
status: Literal["healthy", "unhealthy"]
6+
api_version: str
7+
services: Dict[str, Literal["up", "down"]]

app/schemas/prediction.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from pydantic import BaseModel, Field
2+
from typing import Literal, Optional
3+
from enum import Enum
4+
5+
class DiseaseType(str, Enum):
6+
PNEUMONIA = "Pneumonia"
7+
MELANOMA = "Melanoma"
8+
BRAIN = "Brain"
9+
HEART = "Heart"
10+
11+
class PredictionRequest(BaseModel):
12+
disease_type: DiseaseType = Field(..., description="Type of disease to predict")
13+
image_base64: str = Field(..., description="Base64 encoded image data")
14+
15+
class PredictionResponse(BaseModel):
16+
disease_type: DiseaseType
17+
prediction: str
18+
confidence: float = Field(..., ge=0.0, le=1.0)
19+
analysis: str
20+
status: Literal["success", "error"] = "success"
21+
error_message: Optional[str] = None

app/services/Brain.py

Whitespace-only changes.

app/services/Eye.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import torch
2+
from torchvision import transforms
3+
from PIL import Image
4+
import logging
5+
from pathlib import Path
6+
from typing import Optional, Tuple
7+
from app.config import get_settings
8+
9+
settings = get_settings()
10+
11+
class Eye:
12+
MODEL_PATH = settings.EYE_MODEL_PATH
13+
def __init__(self):
14+
self.model = self._load_model()
15+
self.transform = self._get_transforms()
16+
17+
def _get_transforms(self) -> torch.transforms.Compose:
18+
# Define the transformations
19+
return transforms.Compose([
20+
transforms.Resize((224, 224)),
21+
transforms.ToTensor(),
22+
transforms.Normalize(
23+
mean=[0.485, 0.456, 0.406],
24+
std=[0.229, 0.224, 0.225]
25+
)
26+
])
27+
28+
def _load_model(self) -> torch.nn.Module:
29+
"""Load and initialize the PyTorch model."""
30+
try:
31+
# Ensure the model path exists
32+
model_path = Path(self.MODEL_PATH)
33+
if not model_path.exists():
34+
raise FileNotFoundError(f"Model file not found at {model_path}")
35+
model = torch.load(model_path, map_location=torch.device("cpu"))
36+
# Set the model to evaluation mode
37+
model.eval()
38+
logging.info("Model loaded successfully")
39+
return model
40+
except Exception as e:
41+
logging.error(f"Model loading error: {str(e)}")
42+
43+
def predict_with_torch(self, image_path: str) -> Tuple[str, float]:
44+
"""
45+
Predict using PyTorch model.
46+
Returns prediction and confidence score.
47+
"""
48+
try:
49+
image = Image.open(image_path).convert("RGB")
50+
image_tensor = self.transform(image).unsqueeze(0)
51+
52+
with torch.no_grad():
53+
outputs = self.model(image_tensor)
54+
probabilities = torch.softmax(outputs, dim=1)
55+
confidence, predicted = torch.max(probabilities, 1)
56+
57+
return self.CLASSES[predicted.item()], confidence.item()
58+
except Exception as e:
59+
logging.error(f"Prediction error: {str(e)}")
60+
raise RuntimeError("Error during model prediction.")
61+

app/services/Heart.py

Whitespace-only changes.

app/services/Pneumonia.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import torch
2+
from torchvision import transforms
3+
from PIL import Image
4+
import logging
5+
from pathlib import Path
6+
from typing import Optional, Tuple
7+
from app.config import get_settings
8+
9+
settings = get_settings()
10+
11+
class Pneumonia:
12+
CLASSES = ["Normal", "Pneumonia"]
13+
MODEL_PATH = settings.PNEUMONIA_MODEL_PATH
14+
15+
def __init__(self):
16+
self.model = self._load_model()
17+
self.transform = self._get_transforms()
18+
19+
def _load_model(self) -> torch.nn.Module:
20+
"""Load and initialize the PyTorch model."""
21+
try:
22+
# Ensure the model path exists
23+
model_path = Path(self.MODEL_PATH)
24+
if not model_path.exists():
25+
raise FileNotFoundError(f"Model file not found at {model_path}")
26+
27+
model = torch.load(model_path, map_location=torch.device("cpu"))
28+
model.eval()
29+
logging.info("Model loaded successfully")
30+
return model
31+
32+
except Exception as e:
33+
logging.error(f"Model loading error: {str(e)}")
34+
35+
@staticmethod
36+
def _get_transforms():
37+
"""Define image transformations."""
38+
return transforms.Compose([
39+
transforms.Resize((224, 224)),
40+
transforms.ToTensor(),
41+
transforms.Normalize(
42+
mean=[0.485, 0.456, 0.406],
43+
std=[0.229, 0.224, 0.225]
44+
)
45+
])
46+
47+
def predict_with_torch(self, image_path: str) -> Tuple[str, float]:
48+
"""
49+
Predict using PyTorch model.
50+
Returns prediction and confidence score.
51+
"""
52+
try:
53+
image = Image.open(image_path).convert("RGB")
54+
image_tensor = self.transform(image).unsqueeze(0)
55+
56+
with torch.no_grad():
57+
outputs = self.model(image_tensor)
58+
probabilities = torch.softmax(outputs, dim=1)
59+
confidence, predicted = torch.max(probabilities, 1)
60+
61+
return self.CLASSES[predicted.item()], confidence.item()
62+
except Exception as e:
63+
logging.error(f"Prediction error: {str(e)}")
64+
raise RuntimeError("Error during model prediction.")

0 commit comments

Comments
 (0)