Emmanuel Frimpong Asante commited on
Commit
f6bbd69
·
1 Parent(s): 712de7e

update space

Browse files
.idea/workspace.xml CHANGED
@@ -5,10 +5,11 @@
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,7 +52,7 @@
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",
@@ -64,11 +65,11 @@
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,14 +131,6 @@
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>
136
- <option name="number" value="00075" />
137
- <option name="presentableId" value="LOCAL-00075" />
138
- <option name="project" value="LOCAL" />
139
- <updated>1730400686897</updated>
140
- </task>
141
  <task id="LOCAL-00076" summary="update space">
142
  <option name="closed" value="true" />
143
  <created>1730402280098</created>
@@ -522,7 +515,15 @@
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">
 
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$/models/auth.h5" 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$/models/Final_Chicken_disease_model.h5" beforeDir="false" afterPath="$PROJECT_DIR$/models/diseases.h5" afterDir="false" />
11
+ <change beforePath="$PROJECT_DIR$/services/convert_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/services/convert_model.py" afterDir="false" />
12
+ <change beforePath="$PROJECT_DIR$/services/disease_detection_service.py" beforeDir="false" afterPath="$PROJECT_DIR$/services/disease_detection_service.py" afterDir="false" />
13
  </list>
14
  <option name="SHOW_DIALOG" value="false" />
15
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
 
52
  "RunOnceActivity.ShowReadmeOnStart": "true",
53
  "git-widget-placeholder": "main",
54
  "ignore.virus.scanning.warn.message": "true",
55
+ "last_opened_file_path": "C:/git/Generative_AI_with_poultry_disease_detection_system_v2/models",
56
  "list.type.of.created.stylesheet": "CSS",
57
  "node.js.detected.package.eslint": "true",
58
  "node.js.detected.package.tslint": "true",
 
65
  }]]></component>
66
  <component name="RecentsManager">
67
  <key name="CopyFile.RECENT_KEYS">
68
+ <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\models" />
69
  <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2" />
70
  <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static" />
71
  <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\tasks" />
72
  <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\templates\todo" />
 
73
  </key>
74
  <key name="MoveFile.RECENT_KEYS">
75
  <recent name="C:\git\Generative_AI_with_poultry_disease_detection_system_v2\static\images" />
 
131
  <workItem from="1730397485849" duration="22781000" />
132
  <workItem from="1730454506390" duration="12672000" />
133
  </task>
 
 
 
 
 
 
 
 
134
  <task id="LOCAL-00076" summary="update space">
135
  <option name="closed" value="true" />
136
  <created>1730402280098</created>
 
515
  <option name="project" value="LOCAL" />
516
  <updated>1730488911425</updated>
517
  </task>
518
+ <task id="LOCAL-00124" summary="update space">
519
+ <option name="closed" value="true" />
520
+ <created>1730490013545</created>
521
+ <option name="number" value="00124" />
522
+ <option name="presentableId" value="LOCAL-00124" />
523
+ <option name="project" value="LOCAL" />
524
+ <updated>1730490013545</updated>
525
+ </task>
526
+ <option name="localTasksCounter" value="125" />
527
  <servers />
528
  </component>
529
  <component name="TypeScriptGeneratedFilesManager">
models/auth.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:55ca5e07d8f4d45eab021364be749ced18402f85f5edb7425486ed76ea5c3093
3
+ size 234256896
models/{Final_Chicken_disease_model.h5 → diseases.h5} RENAMED
File without changes
services/convert_model.py CHANGED
@@ -2,7 +2,7 @@
2
 
3
  import tensorflow as tf
4
 
5
- MODEL_PATH = "models/Final_Chicken_disease_model.h5"
6
  NEW_MODEL_PATH = "models/Final_Chicken_disease_model"
7
 
8
  # Load the .h5 model
 
2
 
3
  import tensorflow as tf
4
 
5
+ MODEL_PATH = "models/diseases.h5"
6
  NEW_MODEL_PATH = "models/Final_Chicken_disease_model"
7
 
8
  # Load the .h5 model
services/disease_detection_service.py CHANGED
@@ -3,19 +3,20 @@
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
10
  from transformers import AutoTokenizer, AutoModelForCausalLM
11
  from services.utils import db # MongoDB instance from utils
12
  import configparser
13
 
14
- # Configure logging with advanced settings for detailed output
15
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
  logger = logging.getLogger(__name__)
17
 
18
- # Load and configure Hugging Face API token for secure model access
19
  HF_TOKEN = os.environ.get('HF_Token')
20
  if HF_TOKEN:
21
  login(token=HF_TOKEN, add_to_git_credential=True)
@@ -23,44 +24,65 @@ if HF_TOKEN:
23
  else:
24
  logger.warning("Hugging Face token missing. Please set HF_Token in environment variables.")
25
 
26
- # Load configuration for model paths and other settings from 'config.ini'
27
  config = configparser.ConfigParser()
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
37
  llama_model, llama_tokenizer = None, None
38
  model_loading_event = threading.Event()
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)
51
  raise RuntimeError("Failed to load disease detection model") from e
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:
@@ -69,11 +91,11 @@ def load_llama_model():
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
@@ -86,63 +108,65 @@ recommendations = {
86
  3: 'Administer antibiotics as prescribed by a veterinarian and ensure biosecurity.'
87
  }
88
 
89
- class PoultryFarmBot:
90
- """Poultry Farm Bot for disease prediction and response generation."""
91
 
92
- def __init__(self, db):
93
- """Initialize bot with MongoDB access for record-keeping."""
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
 
 
 
 
 
 
 
 
 
 
110
 
111
  def predict_disease(self, image: np.ndarray):
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
125
  detailed_response = self.generate_detailed_response(disease_name, disease_status, recommendation)
126
  return detailed_response, disease_name, disease_status, recommendation, confidence
127
  except Exception as e:
128
- logger.error("Error in disease prediction", exc_info=True)
129
  return "Prediction failed.", None, None, None, None
130
 
131
- def generate_detailed_response(self, disease_name: str, status: str, recommendation: str) -> str:
132
- """Generate detailed response using Llama model based on prediction."""
133
- prompt = (
134
- f"The detected disease is {disease_name}, classified as {status}. "
135
- f"Suggested action: {recommendation}. "
136
- f"Here is additional information on {disease_name}: causes, symptoms, and effective management."
137
- )
138
- response = self.llama_response(prompt)
139
- return response.replace(prompt, "").strip()
140
-
141
  def llama_response(self, prompt: str) -> str:
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:
@@ -155,10 +179,12 @@ class PoultryFarmBot:
155
  return "Provide a valid poultry fecal image.", None, None, None, None
156
  return self.predict_disease(image)
157
 
 
158
  # Load models upon service startup
159
  disease_model = load_disease_model()
 
160
  llama_model, llama_tokenizer = load_llama_model()
161
 
162
  # Initialize the bot instance with MongoDB
163
- bot = PoultryFarmBot(db)
164
  logger.info("Bot instance initialized with models loaded.")
 
3
  import os
4
  import logging
5
  import threading
6
+ import tensorflow as tf
7
  import cv2
8
  import numpy as np
9
+ from keras.models import load_model
10
  from huggingface_hub import login
11
  from transformers import AutoTokenizer, AutoModelForCausalLM
12
  from services.utils import db # MongoDB instance from utils
13
  import configparser
14
 
15
+ # Configure logging
16
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
17
  logger = logging.getLogger(__name__)
18
 
19
+ # Load Hugging Face API token for secure model access
20
  HF_TOKEN = os.environ.get('HF_Token')
21
  if HF_TOKEN:
22
  login(token=HF_TOKEN, add_to_git_credential=True)
 
24
  else:
25
  logger.warning("Hugging Face token missing. Please set HF_Token in environment variables.")
26
 
27
+ # Load configuration for model paths
28
  config = configparser.ConfigParser()
29
  config.read('config.ini')
30
  logger.info("Configuration loaded from config.ini.")
31
 
32
+ # Configure TensorFlow for GPU and mixed precision if supported
33
+ gpu_devices = tf.config.list_physical_devices('GPU')
34
+ if gpu_devices:
35
+ for gpu in gpu_devices:
36
+ tf.config.experimental.set_memory_growth(gpu, True)
37
+ if tf.config.experimental.get_device_details(gpu_devices[0]).get('compute_capability', (0, 0))[0] >= 7:
38
+ from tensorflow.keras import mixed_precision
39
+ policy = mixed_precision.Policy('mixed_float16')
40
+ mixed_precision.set_global_policy(policy)
41
+ logger.info("Mixed precision enabled on supported GPU.")
42
+ else:
43
+ logger.info("No GPU detected, using CPU without mixed precision.")
44
 
45
  # Global model variables and threading event for synchronization
46
+ disease_model, auth_model = None, None
47
  llama_model, llama_tokenizer = None, None
48
  model_loading_event = threading.Event()
49
 
50
  # Function to load the disease detection model
51
  def load_disease_model():
52
+ """Load the disease detection model."""
53
  try:
54
+ model_path = config.get('MODELS', 'DISEASE_MODEL_PATH', fallback="models/diseases.h5")
55
+ device = tf.config.list_logical_devices('GPU')[0] if gpu_devices else tf.config.list_logical_devices('CPU')[0]
56
+ with tf.device(device.name):
57
+ model = load_model(model_path, compile=True)
58
+ logger.info(f"Disease detection model loaded successfully on {device.name}.")
59
  return model
60
  except Exception as e:
61
  logger.error("Error loading disease detection model", exc_info=True)
62
  raise RuntimeError("Failed to load disease detection model") from e
63
 
64
+ # Function to load the authentication model
65
+ def load_auth_model():
66
+ """Load the authentication model to verify poultry images."""
67
+ try:
68
+ auth_model_path = config.get('MODELS', 'AUTH_MODEL_PATH', fallback="models/auth.h5")
69
+ auth_model = load_model(auth_model_path, compile=True)
70
+ logger.info("Authentication model loaded successfully.")
71
+ return auth_model
72
+ except Exception as e:
73
+ logger.error("Error loading authentication model", exc_info=True)
74
+ raise RuntimeError("Failed to load authentication model") from e
75
+
76
  # Function to load the Llama 3.2 model for language generation
77
  def load_llama_model():
78
  """Load the Llama model and tokenizer for language generation."""
79
  global llama_model, llama_tokenizer
80
  try:
81
  logger.info("Loading Llama 3.2 model and tokenizer using PyTorch-compatible model.")
82
+ model_name = "meta-llama/Llama-3.2-1B"
83
 
 
84
  llama_tokenizer = AutoTokenizer.from_pretrained(model_name)
85
+ llama_model = AutoModelForCausalLM.from_pretrained(model_name)
86
 
87
  # Add a padding token if it's missing
88
  if llama_tokenizer.pad_token is None:
 
91
  llama_model.resize_token_embeddings(len(llama_tokenizer))
92
 
93
  logger.info("Llama model and tokenizer loaded successfully.")
94
+ model_loading_event.set()
95
  return llama_model, llama_tokenizer
96
  except Exception as e:
97
  logger.error("Failed to load Llama model", exc_info=True)
98
+ model_loading_event.set()
99
  raise RuntimeError("Failed to load the Llama 3.2 model. Verify compatibility.")
100
 
101
  # Disease mappings and recommended treatments
 
108
  3: 'Administer antibiotics as prescribed by a veterinarian and ensure biosecurity.'
109
  }
110
 
 
 
111
 
112
+ class PoultryFarmBot:
113
+ def __init__(self, disease_model, auth_model):
114
+ self.disease_model = disease_model
115
+ self.auth_model = auth_model
116
+ logging.basicConfig(level=logging.INFO)
117
+ self.logger = logging.getLogger(__name__)
118
 
119
+ def preprocess_image(self, image: np.ndarray) -> np.ndarray:
120
  """Preprocess the input image for model prediction."""
121
  try:
 
 
122
  image = cv2.resize(image, (224, 224))
123
+ return image / 255.0 # Normalize
 
 
 
124
  except Exception as e:
125
+ self.logger.error("Error in image preprocessing", exc_info=True)
126
+ raise ValueError("Invalid image format or empty image provided.")
127
+
128
+ def generate_detailed_response(self, disease_name: str, status: str, recommendation: str) -> str:
129
+ """Generate detailed response using Llama model based on prediction."""
130
+ prompt = (
131
+ f"The detected disease is {disease_name}, classified as {status}. "
132
+ f"Suggested action: {recommendation}. "
133
+ f"Here is additional information on {disease_name}: causes, symptoms, and effective management."
134
+ )
135
+ response = self.llama_response(prompt)
136
+ return response.replace(prompt, "").strip()
137
 
138
  def predict_disease(self, image: np.ndarray):
139
  """Predict disease from preprocessed image and provide detailed results."""
140
  try:
141
  preprocessed_image = self.preprocess_image(image)
142
+
143
+ # Use auth_model to verify the image is poultry-related
144
+ is_poultry = self.auth_model.predict(preprocessed_image.reshape(1, 224, 224, 3)).argmax()
145
+ if is_poultry != 0:
146
+ self.logger.info("Image not recognized as poultry.")
147
+ return "Unknown Image", "N/A", "N/A", "Image not recognized as poultry.", None
148
+
149
+ # Predict disease if image is verified
150
+ prediction = self.disease_model.predict(preprocessed_image.reshape(1, 224, 224, 3))
151
+ predicted_class = prediction.argmax()
152
  disease_name = name_disease.get(predicted_class, "Unknown disease")
153
  disease_status = status_map.get(predicted_class, "Unknown status")
154
  recommendation = recommendations.get(predicted_class, "No recommendation available")
155
+ confidence = prediction[0][predicted_class] * 100
156
+ self.logger.info(f"Disease Prediction: {disease_name} with {confidence:.2f}% confidence.")
157
 
158
  # Generate a detailed response using Llama model
159
  detailed_response = self.generate_detailed_response(disease_name, disease_status, recommendation)
160
  return detailed_response, disease_name, disease_status, recommendation, confidence
161
  except Exception as e:
162
+ self.logger.error("Error in disease prediction", exc_info=True)
163
  return "Prediction failed.", None, None, None, None
164
 
 
 
 
 
 
 
 
 
 
 
165
  def llama_response(self, prompt: str) -> str:
166
  """Generate a response from the Llama model based on a prompt."""
167
  try:
168
  max_length = min(len(prompt) + 50, 512)
169
+ inputs = llama_tokenizer(prompt, return_tensors="tf", max_length=max_length, truncation=True, padding=True)
170
  outputs = llama_model.generate(inputs["input_ids"], max_length=max_length, do_sample=True, temperature=0.7, top_p=0.9)
171
  return llama_tokenizer.decode(outputs[0], skip_special_tokens=True)
172
  except Exception as e:
 
179
  return "Provide a valid poultry fecal image.", None, None, None, None
180
  return self.predict_disease(image)
181
 
182
+
183
  # Load models upon service startup
184
  disease_model = load_disease_model()
185
+ auth_model = load_auth_model()
186
  llama_model, llama_tokenizer = load_llama_model()
187
 
188
  # Initialize the bot instance with MongoDB
189
+ bot = PoultryFarmBot(disease_model, auth_model)
190
  logger.info("Bot instance initialized with models loaded.")