Emmanuel Frimpong Asante
commited on
Commit
·
712de7e
1
Parent(s):
6a16cb0
update space
Browse files- .idea/workspace.xml +23 -23
- app.py +4 -4
- requirements.txt +2 -2
- services/disease_detection_service.py +40 -50
- training/resnet-18-model-for-poultry-disease-classification.ipynb +0 -0
.idea/workspace.xml
CHANGED
@@ -5,10 +5,10 @@
|
|
5 |
</component>
|
6 |
<component name="ChangeListManager">
|
7 |
<list default="true" id="27c9ae1a-a6fa-4472-8bcd-a7087620894b" name="Changes" comment="update space">
|
8 |
-
<change afterPath="$PROJECT_DIR$/
|
9 |
-
<change afterPath="$PROJECT_DIR$/scripts/populate_inventory.py" afterDir="false" />
|
10 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
11 |
-
<change beforePath="$PROJECT_DIR$/
|
|
|
12 |
</list>
|
13 |
<option name="SHOW_DIALOG" value="false" />
|
14 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
@@ -51,24 +51,24 @@
|
|
51 |
"RunOnceActivity.ShowReadmeOnStart": "true",
|
52 |
"git-widget-placeholder": "main",
|
53 |
"ignore.virus.scanning.warn.message": "true",
|
54 |
-
"last_opened_file_path": "C:/git/Generative_AI_with_poultry_disease_detection_system_v2
|
55 |
"list.type.of.created.stylesheet": "CSS",
|
56 |
"node.js.detected.package.eslint": "true",
|
57 |
"node.js.detected.package.tslint": "true",
|
58 |
"node.js.selected.package.eslint": "(autodetect)",
|
59 |
"node.js.selected.package.tslint": "(autodetect)",
|
60 |
"nodejs_package_manager_path": "npm",
|
61 |
-
"settings.editor.selected.configurable": "
|
62 |
"vue.rearranger.settings.migration": "true"
|
63 |
}
|
64 |
}]]></component>
|
65 |
<component name="RecentsManager">
|
66 |
<key name="CopyFile.RECENT_KEYS">
|
|
|
67 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static" />
|
68 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\tasks" />
|
69 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\todo" />
|
70 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates" />
|
71 |
-
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static\images" />
|
72 |
</key>
|
73 |
<key name="MoveFile.RECENT_KEYS">
|
74 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static\images" />
|
@@ -130,22 +130,6 @@
|
|
130 |
<workItem from="1730397485849" duration="22781000" />
|
131 |
<workItem from="1730454506390" duration="12672000" />
|
132 |
</task>
|
133 |
-
<task id="LOCAL-00073" summary="update space">
|
134 |
-
<option name="closed" value="true" />
|
135 |
-
<created>1730399007546</created>
|
136 |
-
<option name="number" value="00073" />
|
137 |
-
<option name="presentableId" value="LOCAL-00073" />
|
138 |
-
<option name="project" value="LOCAL" />
|
139 |
-
<updated>1730399007546</updated>
|
140 |
-
</task>
|
141 |
-
<task id="LOCAL-00074" summary="update space">
|
142 |
-
<option name="closed" value="true" />
|
143 |
-
<created>1730399542427</created>
|
144 |
-
<option name="number" value="00074" />
|
145 |
-
<option name="presentableId" value="LOCAL-00074" />
|
146 |
-
<option name="project" value="LOCAL" />
|
147 |
-
<updated>1730399542427</updated>
|
148 |
-
</task>
|
149 |
<task id="LOCAL-00075" summary="update space">
|
150 |
<option name="closed" value="true" />
|
151 |
<created>1730400686897</created>
|
@@ -522,7 +506,23 @@
|
|
522 |
<option name="project" value="LOCAL" />
|
523 |
<updated>1730488078280</updated>
|
524 |
</task>
|
525 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
526 |
<servers />
|
527 |
</component>
|
528 |
<component name="TypeScriptGeneratedFilesManager">
|
|
|
5 |
</component>
|
6 |
<component name="ChangeListManager">
|
7 |
<list default="true" id="27c9ae1a-a6fa-4472-8bcd-a7087620894b" name="Changes" comment="update space">
|
8 |
+
<change afterPath="$PROJECT_DIR$/training/resnet-18-model-for-poultry-disease-classification.ipynb" afterDir="false" />
|
|
|
9 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
10 |
+
<change beforePath="$PROJECT_DIR$/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/app.py" afterDir="false" />
|
11 |
+
<change beforePath="$PROJECT_DIR$/requirements.txt" beforeDir="false" afterPath="$PROJECT_DIR$/requirements.txt" afterDir="false" />
|
12 |
</list>
|
13 |
<option name="SHOW_DIALOG" value="false" />
|
14 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
|
51 |
"RunOnceActivity.ShowReadmeOnStart": "true",
|
52 |
"git-widget-placeholder": "main",
|
53 |
"ignore.virus.scanning.warn.message": "true",
|
54 |
+
"last_opened_file_path": "C:/git/Generative_AI_with_poultry_disease_detection_system_v2",
|
55 |
"list.type.of.created.stylesheet": "CSS",
|
56 |
"node.js.detected.package.eslint": "true",
|
57 |
"node.js.detected.package.tslint": "true",
|
58 |
"node.js.selected.package.eslint": "(autodetect)",
|
59 |
"node.js.selected.package.tslint": "(autodetect)",
|
60 |
"nodejs_package_manager_path": "npm",
|
61 |
+
"settings.editor.selected.configurable": "swagger",
|
62 |
"vue.rearranger.settings.migration": "true"
|
63 |
}
|
64 |
}]]></component>
|
65 |
<component name="RecentsManager">
|
66 |
<key name="CopyFile.RECENT_KEYS">
|
67 |
+
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2" />
|
68 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static" />
|
69 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\tasks" />
|
70 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\todo" />
|
71 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates" />
|
|
|
72 |
</key>
|
73 |
<key name="MoveFile.RECENT_KEYS">
|
74 |
<recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static\images" />
|
|
|
130 |
<workItem from="1730397485849" duration="22781000" />
|
131 |
<workItem from="1730454506390" duration="12672000" />
|
132 |
</task>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
<task id="LOCAL-00075" summary="update space">
|
134 |
<option name="closed" value="true" />
|
135 |
<created>1730400686897</created>
|
|
|
506 |
<option name="project" value="LOCAL" />
|
507 |
<updated>1730488078280</updated>
|
508 |
</task>
|
509 |
+
<task id="LOCAL-00122" summary="update space">
|
510 |
+
<option name="closed" value="true" />
|
511 |
+
<created>1730488664527</created>
|
512 |
+
<option name="number" value="00122" />
|
513 |
+
<option name="presentableId" value="LOCAL-00122" />
|
514 |
+
<option name="project" value="LOCAL" />
|
515 |
+
<updated>1730488664527</updated>
|
516 |
+
</task>
|
517 |
+
<task id="LOCAL-00123" summary="update space">
|
518 |
+
<option name="closed" value="true" />
|
519 |
+
<created>1730488911425</created>
|
520 |
+
<option name="number" value="00123" />
|
521 |
+
<option name="presentableId" value="LOCAL-00123" />
|
522 |
+
<option name="project" value="LOCAL" />
|
523 |
+
<updated>1730488911425</updated>
|
524 |
+
</task>
|
525 |
+
<option name="localTasksCounter" value="124" />
|
526 |
<servers />
|
527 |
</component>
|
528 |
<component name="TypeScriptGeneratedFilesManager">
|
app.py
CHANGED
@@ -5,7 +5,7 @@ from fastapi import FastAPI, Request, HTTPException, BackgroundTasks, Depends
|
|
5 |
from fastapi.templating import Jinja2Templates
|
6 |
from fastapi.responses import HTMLResponse, RedirectResponse
|
7 |
from fastapi.staticfiles import StaticFiles
|
8 |
-
import tensorflow as tf
|
9 |
import os
|
10 |
import logging
|
11 |
import time
|
@@ -20,9 +20,9 @@ from huggingface_hub import login
|
|
20 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
21 |
logger = logging.getLogger(__name__)
|
22 |
|
23 |
-
# Check GPU availability for TensorFlow
|
24 |
-
gpu_devices = tf.config.list_physical_devices('GPU')
|
25 |
-
logger.info(f"{'GPUs available' if gpu_devices else 'Using CPU'} for TensorFlow")
|
26 |
|
27 |
# Initialize FastAPI app and templates
|
28 |
app = FastAPI()
|
|
|
5 |
from fastapi.templating import Jinja2Templates
|
6 |
from fastapi.responses import HTMLResponse, RedirectResponse
|
7 |
from fastapi.staticfiles import StaticFiles
|
8 |
+
# import tensorflow as tf
|
9 |
import os
|
10 |
import logging
|
11 |
import time
|
|
|
20 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
21 |
logger = logging.getLogger(__name__)
|
22 |
|
23 |
+
# # Check GPU availability for TensorFlow
|
24 |
+
# gpu_devices = tf.config.list_physical_devices('GPU')
|
25 |
+
# logger.info(f"{'GPUs available' if gpu_devices else 'Using CPU'} for TensorFlow")
|
26 |
|
27 |
# Initialize FastAPI app and templates
|
28 |
app = FastAPI()
|
requirements.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
-
tensorflow[and-cuda]
|
2 |
opencv-python-headless
|
3 |
fastapi
|
4 |
passlib[bcrypt]
|
5 |
pydantic[email]
|
6 |
pymongo
|
7 |
python-dotenv
|
8 |
-
python-jose[cryptography]
|
9 |
starlette
|
10 |
uvicorn
|
11 |
jinja2
|
|
|
1 |
+
tensorflow[and-cuda]
|
2 |
opencv-python-headless
|
3 |
fastapi
|
4 |
passlib[bcrypt]
|
5 |
pydantic[email]
|
6 |
pymongo
|
7 |
python-dotenv
|
8 |
+
python-jose[cryptography]
|
9 |
starlette
|
10 |
uvicorn
|
11 |
jinja2
|
services/disease_detection_service.py
CHANGED
@@ -3,9 +3,7 @@
|
|
3 |
import os
|
4 |
import logging
|
5 |
import threading
|
6 |
-
import tensorflow as tf
|
7 |
import torch
|
8 |
-
from keras.models import load_model
|
9 |
import cv2
|
10 |
import numpy as np
|
11 |
from huggingface_hub import login
|
@@ -30,18 +28,9 @@ config = configparser.ConfigParser()
|
|
30 |
config.read('config.ini')
|
31 |
logger.info("Configuration loaded from config.ini.")
|
32 |
|
33 |
-
#
|
34 |
-
|
35 |
-
|
36 |
-
for gpu in gpu_devices:
|
37 |
-
tf.config.experimental.set_memory_growth(gpu, True)
|
38 |
-
if tf.config.experimental.get_device_details(gpu_devices[0]).get('compute_capability', (0, 0))[0] >= 7:
|
39 |
-
from tensorflow.keras import mixed_precision
|
40 |
-
policy = mixed_precision.Policy('mixed_float16')
|
41 |
-
mixed_precision.set_global_policy(policy)
|
42 |
-
logger.info("Mixed precision enabled on supported GPU.")
|
43 |
-
else:
|
44 |
-
logger.info("No GPU detected, using CPU without mixed precision.")
|
45 |
|
46 |
# Global model variables and threading event for synchronization
|
47 |
disease_model = None
|
@@ -50,13 +39,12 @@ model_loading_event = threading.Event()
|
|
50 |
|
51 |
# Function to load the disease detection model
|
52 |
def load_disease_model():
|
53 |
-
"""Load the pre-trained model for poultry disease detection."""
|
54 |
try:
|
55 |
-
model_path = config.get('MODELS', 'DISEASE_MODEL_PATH', fallback="models/Final_Chicken_disease_model.
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
logger.info(f"Disease detection model loaded successfully on {device.name}.")
|
60 |
return model
|
61 |
except Exception as e:
|
62 |
logger.error("Error loading disease detection model", exc_info=True)
|
@@ -64,29 +52,29 @@ def load_disease_model():
|
|
64 |
|
65 |
# Function to load the Llama 3.2 model for language generation
|
66 |
def load_llama_model():
|
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 |
# Disease mappings and recommended treatments
|
92 |
name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
|
@@ -106,15 +94,16 @@ class PoultryFarmBot:
|
|
106 |
self.db = db
|
107 |
logger.info("PoultryFarmBot initialized with MongoDB access.")
|
108 |
|
109 |
-
def preprocess_image(self, image: np.ndarray) ->
|
110 |
"""Preprocess the input image for model prediction."""
|
111 |
try:
|
112 |
if image is None or image.size == 0:
|
113 |
raise ValueError("Invalid or empty image.")
|
114 |
image = cv2.resize(image, (224, 224))
|
115 |
-
image = np.
|
|
|
116 |
logger.info("Image preprocessed successfully.")
|
117 |
-
return image
|
118 |
except Exception as e:
|
119 |
logger.error("Error in image preprocessing", exc_info=True)
|
120 |
raise
|
@@ -123,12 +112,13 @@ class PoultryFarmBot:
|
|
123 |
"""Predict disease from preprocessed image and provide detailed results."""
|
124 |
try:
|
125 |
preprocessed_image = self.preprocess_image(image)
|
126 |
-
|
127 |
-
|
|
|
128 |
disease_name = name_disease.get(predicted_class, "Unknown disease")
|
129 |
disease_status = status_map.get(predicted_class, "Unknown status")
|
130 |
recommendation = recommendations.get(predicted_class, "No recommendation available")
|
131 |
-
confidence = prediction[0][predicted_class] * 100
|
132 |
logger.info(f"Disease Prediction: {disease_name} with {confidence:.2f}% confidence.")
|
133 |
|
134 |
# Generate a detailed response using Llama model
|
@@ -152,7 +142,7 @@ class PoultryFarmBot:
|
|
152 |
"""Generate a response from the Llama model based on a prompt."""
|
153 |
try:
|
154 |
max_length = min(len(prompt) + 50, 512)
|
155 |
-
inputs = llama_tokenizer(prompt, return_tensors="
|
156 |
outputs = llama_model.generate(inputs["input_ids"], max_length=max_length, do_sample=True, temperature=0.7, top_p=0.9)
|
157 |
return llama_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
158 |
except Exception as e:
|
|
|
3 |
import os
|
4 |
import logging
|
5 |
import threading
|
|
|
6 |
import torch
|
|
|
7 |
import cv2
|
8 |
import numpy as np
|
9 |
from huggingface_hub import login
|
|
|
28 |
config.read('config.ini')
|
29 |
logger.info("Configuration loaded from config.ini.")
|
30 |
|
31 |
+
# Check for GPU availability and set device
|
32 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
33 |
+
logger.info(f"Using device: {device}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
# Global model variables and threading event for synchronization
|
36 |
disease_model = None
|
|
|
39 |
|
40 |
# Function to load the disease detection model
|
41 |
def load_disease_model():
|
42 |
+
"""Load the pre-trained PyTorch model for poultry disease detection."""
|
43 |
try:
|
44 |
+
model_path = config.get('MODELS', 'DISEASE_MODEL_PATH', fallback="models/Final_Chicken_disease_model.pth")
|
45 |
+
model = torch.load(model_path, map_location=device)
|
46 |
+
model.eval() # Set model to evaluation mode
|
47 |
+
logger.info("Disease detection model loaded successfully.")
|
|
|
48 |
return model
|
49 |
except Exception as e:
|
50 |
logger.error("Error loading disease detection model", exc_info=True)
|
|
|
52 |
|
53 |
# Function to load the Llama 3.2 model for language generation
|
54 |
def load_llama_model():
|
55 |
+
"""Load the Llama model and tokenizer for language generation."""
|
56 |
+
global llama_model, llama_tokenizer
|
57 |
+
try:
|
58 |
+
logger.info("Loading Llama 3.2 model and tokenizer using PyTorch-compatible model.")
|
59 |
+
model_name = "meta-llama/Llama-3.2-1B" # Update with desired model name
|
60 |
+
|
61 |
+
# Load the tokenizer and model from the Hugging Face hub
|
62 |
+
llama_tokenizer = AutoTokenizer.from_pretrained(model_name)
|
63 |
+
llama_model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
|
64 |
+
|
65 |
+
# Add a padding token if it's missing
|
66 |
+
if llama_tokenizer.pad_token is None:
|
67 |
+
logger.info("Adding padding token to tokenizer.")
|
68 |
+
llama_tokenizer.add_special_tokens({'pad_token': '[PAD]'})
|
69 |
+
llama_model.resize_token_embeddings(len(llama_tokenizer))
|
70 |
+
|
71 |
+
logger.info("Llama model and tokenizer loaded successfully.")
|
72 |
+
model_loading_event.set() # Signal successful loading
|
73 |
+
return llama_model, llama_tokenizer
|
74 |
+
except Exception as e:
|
75 |
+
logger.error("Failed to load Llama model", exc_info=True)
|
76 |
+
model_loading_event.set() # Ensure event is set even if loading fails
|
77 |
+
raise RuntimeError("Failed to load the Llama 3.2 model. Verify compatibility.")
|
78 |
|
79 |
# Disease mappings and recommended treatments
|
80 |
name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
|
|
|
94 |
self.db = db
|
95 |
logger.info("PoultryFarmBot initialized with MongoDB access.")
|
96 |
|
97 |
+
def preprocess_image(self, image: np.ndarray) -> torch.Tensor:
|
98 |
"""Preprocess the input image for model prediction."""
|
99 |
try:
|
100 |
if image is None or image.size == 0:
|
101 |
raise ValueError("Invalid or empty image.")
|
102 |
image = cv2.resize(image, (224, 224))
|
103 |
+
image = np.transpose(image, (2, 0, 1)) # Change from HWC to CHW format for PyTorch
|
104 |
+
image = torch.tensor(image, dtype=torch.float32).unsqueeze(0) / 255.0
|
105 |
logger.info("Image preprocessed successfully.")
|
106 |
+
return image.to(device)
|
107 |
except Exception as e:
|
108 |
logger.error("Error in image preprocessing", exc_info=True)
|
109 |
raise
|
|
|
112 |
"""Predict disease from preprocessed image and provide detailed results."""
|
113 |
try:
|
114 |
preprocessed_image = self.preprocess_image(image)
|
115 |
+
with torch.no_grad():
|
116 |
+
prediction = disease_model(preprocessed_image)
|
117 |
+
predicted_class = torch.argmax(prediction, dim=1).item()
|
118 |
disease_name = name_disease.get(predicted_class, "Unknown disease")
|
119 |
disease_status = status_map.get(predicted_class, "Unknown status")
|
120 |
recommendation = recommendations.get(predicted_class, "No recommendation available")
|
121 |
+
confidence = torch.softmax(prediction, dim=1)[0][predicted_class].item() * 100
|
122 |
logger.info(f"Disease Prediction: {disease_name} with {confidence:.2f}% confidence.")
|
123 |
|
124 |
# Generate a detailed response using Llama model
|
|
|
142 |
"""Generate a response from the Llama model based on a prompt."""
|
143 |
try:
|
144 |
max_length = min(len(prompt) + 50, 512)
|
145 |
+
inputs = llama_tokenizer(prompt, return_tensors="pt", max_length=max_length, truncation=True, padding=True).to(device)
|
146 |
outputs = llama_model.generate(inputs["input_ids"], max_length=max_length, do_sample=True, temperature=0.7, top_p=0.9)
|
147 |
return llama_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
148 |
except Exception as e:
|
training/resnet-18-model-for-poultry-disease-classification.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|