Emmanuel Frimpong Asante commited on
Commit
b6da652
·
1 Parent(s): 529f412

update space

Browse files
Files changed (3) hide show
  1. .env +5 -0
  2. app.py +1 -9
  3. services/disease_detection_service.py +76 -27
.env CHANGED
@@ -13,3 +13,8 @@ FROM_EMAIL="your_from_email_address"
13
  # TensorFlow Settings
14
  TF_ENABLE_ONEDNN_OPTS=0
15
  TF_FORCE_GPU_ALLOW_GROWTH=true
 
 
 
 
 
 
13
  # TensorFlow Settings
14
  TF_ENABLE_ONEDNN_OPTS=0
15
  TF_FORCE_GPU_ALLOW_GROWTH=true
16
+
17
+
18
+ # MODELS
19
+ DISEASE_MODEL_PATH=models/Final_Chicken_disease_model.h5
20
+ LLAMA_MODEL_NAME=meta-llama/Llama-3.2-1B
app.py CHANGED
@@ -19,12 +19,6 @@ from huggingface_hub import login
19
  logging.basicConfig(level=logging.INFO)
20
  logger = logging.getLogger(__name__)
21
 
22
- # Load Hugging Face Token
23
- HF_TOKEN = os.environ.get('HF_Token')
24
- if HF_TOKEN:
25
- login(token=HF_TOKEN, add_to_git_credential=True)
26
- else:
27
- logger.warning("Hugging Face token not found in environment variables.")
28
 
29
  # Check GPU availability for TensorFlow
30
  gpu_devices = tf.config.list_physical_devices('GPU')
@@ -46,9 +40,7 @@ else:
46
  logger.error("Static directory not found.")
47
  raise HTTPException(status_code=500, detail="Static directory not found.")
48
 
49
- # Load models at startup
50
- disease_model = load_disease_model()
51
- llama_model, llama_tokenizer = load_llama_model()
52
 
53
  # Include routers for authentication, disease detection, and health dashboard
54
  app.include_router(auth_router, prefix="/auth", tags=["Authentication"])
 
19
  logging.basicConfig(level=logging.INFO)
20
  logger = logging.getLogger(__name__)
21
 
 
 
 
 
 
 
22
 
23
  # Check GPU availability for TensorFlow
24
  gpu_devices = tf.config.list_physical_devices('GPU')
 
40
  logger.error("Static directory not found.")
41
  raise HTTPException(status_code=500, detail="Static directory not found.")
42
 
43
+
 
 
44
 
45
  # Include routers for authentication, disease detection, and health dashboard
46
  app.include_router(auth_router, prefix="/auth", tags=["Authentication"])
services/disease_detection_service.py CHANGED
@@ -9,25 +9,44 @@ import numpy as np
9
  from huggingface_hub import login
10
  from pymongo import MongoClient
11
  from transformers import TFAutoModelForCausalLM, AutoTokenizer
 
12
 
13
  # Logging setup
14
  logging.basicConfig(level=logging.INFO)
15
  logger = logging.getLogger(__name__)
16
 
 
 
 
 
 
 
 
 
17
  # Load environment variables
18
  MONGO_URI = os.getenv("MONGO_URI")
19
  db_client = MongoClient(MONGO_URI)
20
  db = db_client.poultry_farm # MongoDB for record-keeping
21
 
 
 
 
 
22
  # Mixed precision and GPU configuration
23
  gpu_devices = tf.config.list_physical_devices('GPU')
24
  if gpu_devices:
25
  for gpu in gpu_devices:
26
- tf.config.experimental.set_memory_growth(gpu, True)
 
27
  from tensorflow.keras import mixed_precision
28
- policy = mixed_precision.Policy('mixed_float16')
29
- mixed_precision.set_global_policy(policy)
30
- logger.info("Using mixed precision with GPU.")
 
 
 
 
 
31
  else:
32
  logger.info("Using CPU without mixed precision.")
33
 
@@ -35,23 +54,29 @@ else:
35
  def load_disease_model():
36
  """Load the disease detection model."""
37
  try:
38
- model_path = "models/Final_Chicken_disease_model.h5"
 
 
39
  device = '/GPU:0' if gpu_devices else '/CPU:0'
40
  with tf.device(device):
41
  model = load_model(model_path, compile=True)
42
  logger.info(f"Disease detection model loaded successfully on {device}.")
43
  return model
44
  except Exception as e:
45
- logger.error(f"Error loading disease model: {e}")
46
- raise RuntimeError("Failed to load disease detection model")
 
47
 
48
  def load_llama_model():
49
  """Load the Llama 3.2 model for text generation using TensorFlow."""
50
  try:
51
- model_name = "meta-llama/Llama-3.2-1B"
 
 
52
  tokenizer = AutoTokenizer.from_pretrained(model_name)
53
  model = TFAutoModelForCausalLM.from_pretrained(model_name)
54
 
 
55
  if tokenizer.pad_token is None:
56
  tokenizer.add_special_tokens({'pad_token': '[PAD]'})
57
  model.resize_token_embeddings(len(tokenizer))
@@ -59,11 +84,16 @@ def load_llama_model():
59
  logger.info("Llama 3.2 model loaded successfully with TensorFlow.")
60
  return model, tokenizer
61
  except Exception as e:
62
- logger.error(f"Error loading Llama model: {e}")
63
- raise RuntimeError("Failed to load Llama model")
 
64
 
 
 
 
65
 
66
  # Disease mapping and treatment guidelines
 
67
  name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
68
  status_map = {0: 'Critical', 1: 'No issue', 2: 'Critical', 3: 'Critical'}
69
  recommendations = {
@@ -75,66 +105,85 @@ recommendations = {
75
 
76
  class PoultryFarmBot:
77
  def __init__(self, db):
 
78
  self.db = db
79
 
80
- def preprocess_image(self, image):
81
  """Preprocess image for model input."""
82
  try:
 
 
 
 
83
  image = cv2.resize(image, (224, 224))
84
- image = np.expand_dims(image, axis=0) / 255.0 # Normalize and add batch dimension
 
85
  logger.info("Image preprocessed successfully.")
86
  return image
87
  except Exception as e:
88
- logger.error(f"Error in image preprocessing: {e}")
89
- return None
 
90
 
91
- def predict_disease(self, image):
92
  """Predict the disease from a preprocessed image and return detailed information."""
93
- preprocessed_image = self.preprocess_image(image)
94
- if preprocessed_image is None:
95
- return "Image preprocessing failed.", None, None, None
96
-
97
  try:
 
 
 
98
  prediction = disease_model.predict(preprocessed_image)
 
99
  predicted_class = np.argmax(prediction, axis=1).item()
 
100
  disease_name = name_disease.get(predicted_class, "Unknown disease")
101
  disease_status = status_map.get(predicted_class, "Unknown status")
102
  recommendation = recommendations.get(predicted_class, "No recommendation available")
 
103
  confidence = prediction[0][predicted_class] * 100
104
  logger.info(f"Predicted: {disease_name} with {confidence:.2f}% confidence.")
105
 
106
- # Generate detailed response using Llama 3.2
107
  detailed_response = self.generate_detailed_response(disease_name, disease_status, recommendation)
108
  return detailed_response, disease_name, disease_status, recommendation, confidence
109
  except Exception as e:
110
- logger.error(f"Prediction error: {e}")
 
111
  return "Prediction failed.", None, None, None, None
112
 
113
- def generate_detailed_response(self, disease_name, status, recommendation):
114
  """Generate a detailed response using Llama 3.2 model for additional disease insights."""
 
115
  prompt = (
116
  f"The disease detected is {disease_name}, classified as {status}. "
117
  f"Recommended action: {recommendation}. "
118
  f"Here is more information about {disease_name}, including its causes, symptoms, and treatments "
119
  "for effective management on a poultry farm."
120
  )
 
121
  response = self.llama_response(prompt)
 
122
  return response.replace(prompt, "").strip()
123
 
124
- def llama_response(self, prompt):
125
  """Generate a response from the Llama 3.2 model based on a given prompt."""
126
  try:
127
- inputs = llama_tokenizer(prompt, return_tensors="tf", max_length=150, truncation=True, padding=True)
128
- outputs = llama_model.generate(inputs["input_ids"], max_length=150, do_sample=True, temperature=0.7)
 
 
 
129
  return llama_tokenizer.decode(outputs[0], skip_special_tokens=True)
130
  except Exception as e:
131
- logger.error(f"Llama model response error: {e}")
 
132
  return "Error generating detailed response."
133
 
134
- def diagnose_and_respond(self, image):
135
  """Diagnose the disease and respond with detailed information and recommendations."""
 
136
  if image is None or image.size == 0:
137
  return "Please provide a valid poultry fecal image.", None, None, None, None
 
138
  return self.predict_disease(image)
139
 
140
  # Initialize the bot instance
 
9
  from huggingface_hub import login
10
  from pymongo import MongoClient
11
  from transformers import TFAutoModelForCausalLM, AutoTokenizer
12
+ import configparser
13
 
14
  # Logging setup
15
  logging.basicConfig(level=logging.INFO)
16
  logger = logging.getLogger(__name__)
17
 
18
+ # Load Hugging Face Token
19
+ HF_TOKEN = os.environ.get('HF_Token')
20
+ if HF_TOKEN:
21
+ login(token=HF_TOKEN, add_to_git_credential=True)
22
+ else:
23
+ logger.warning("Hugging Face token not found in environment variables.")
24
+
25
+
26
  # Load environment variables
27
  MONGO_URI = os.getenv("MONGO_URI")
28
  db_client = MongoClient(MONGO_URI)
29
  db = db_client.poultry_farm # MongoDB for record-keeping
30
 
31
+ # Load configuration file
32
+ config = configparser.ConfigParser()
33
+ config.read('config.ini')
34
+
35
  # Mixed precision and GPU configuration
36
  gpu_devices = tf.config.list_physical_devices('GPU')
37
  if gpu_devices:
38
  for gpu in gpu_devices:
39
+ # Enable memory growth for each GPU to avoid allocating all memory at once
40
+ tf.config.set_memory_growth(gpu, True)
41
  from tensorflow.keras import mixed_precision
42
+ # Check if GPU supports mixed precision (compute capability >= 7)
43
+ gpu_details = tf.config.experimental.get_device_details(gpu_devices[0])
44
+ if gpu_details.get('compute_capability', (0, 0))[0] >= 7:
45
+ policy = mixed_precision.Policy('mixed_float16')
46
+ mixed_precision.set_global_policy(policy)
47
+ logger.info("Using mixed precision with GPU.")
48
+ else:
49
+ logger.info("GPU detected but does not support mixed precision.")
50
  else:
51
  logger.info("Using CPU without mixed precision.")
52
 
 
54
  def load_disease_model():
55
  """Load the disease detection model."""
56
  try:
57
+ # Load the model path from the configuration file or use the default path
58
+ model_path = config.get('MODELS', 'DISEASE_MODEL_PATH', fallback="models/Final_Chicken_disease_model.h5")
59
+ # Use GPU if available, otherwise use CPU
60
  device = '/GPU:0' if gpu_devices else '/CPU:0'
61
  with tf.device(device):
62
  model = load_model(model_path, compile=True)
63
  logger.info(f"Disease detection model loaded successfully on {device}.")
64
  return model
65
  except Exception as e:
66
+ # Log the error and raise an exception to indicate failure
67
+ logger.error(f"Error loading disease model: {e}", exc_info=True)
68
+ raise RuntimeError("Failed to load disease detection model") from e
69
 
70
  def load_llama_model():
71
  """Load the Llama 3.2 model for text generation using TensorFlow."""
72
  try:
73
+ # Load the model name from environment variable or use the default model
74
+ model_name = os.getenv("LLAMA_MODEL_NAME", "meta-llama/Llama-3.2-1B")
75
+ # Load the tokenizer and model from the Hugging Face hub
76
  tokenizer = AutoTokenizer.from_pretrained(model_name)
77
  model = TFAutoModelForCausalLM.from_pretrained(model_name)
78
 
79
+ # Add padding token if not already present
80
  if tokenizer.pad_token is None:
81
  tokenizer.add_special_tokens({'pad_token': '[PAD]'})
82
  model.resize_token_embeddings(len(tokenizer))
 
84
  logger.info("Llama 3.2 model loaded successfully with TensorFlow.")
85
  return model, tokenizer
86
  except Exception as e:
87
+ # Log the error and raise an exception to indicate failure
88
+ logger.error(f"Error loading Llama model: {e}", exc_info=True)
89
+ raise RuntimeError("Failed to load Llama model") from e
90
 
91
+ # Load models at startup
92
+ disease_model = load_disease_model()
93
+ llama_model, llama_tokenizer = load_llama_model()
94
 
95
  # Disease mapping and treatment guidelines
96
+ # Maps predicted class indices to disease names, status, and treatment recommendations
97
  name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
98
  status_map = {0: 'Critical', 1: 'No issue', 2: 'Critical', 3: 'Critical'}
99
  recommendations = {
 
105
 
106
  class PoultryFarmBot:
107
  def __init__(self, db):
108
+ # Initialize the bot with a reference to the MongoDB database
109
  self.db = db
110
 
111
+ def preprocess_image(self, image: np.ndarray) -> np.ndarray:
112
  """Preprocess image for model input."""
113
  try:
114
+ # Check if the image is valid
115
+ if image is None or image.size == 0:
116
+ raise ValueError("Empty or invalid image provided.")
117
+ # Resize the image to the input size required by the model (224x224)
118
  image = cv2.resize(image, (224, 224))
119
+ # Normalize the image (scaling pixel values to range [0, 1]) and add a batch dimension
120
+ image = np.expand_dims(image, axis=0) / 255.0
121
  logger.info("Image preprocessed successfully.")
122
  return image
123
  except Exception as e:
124
+ # Log the error and raise an exception to indicate failure
125
+ logger.error(f"Error in image preprocessing: {e}", exc_info=True)
126
+ raise
127
 
128
+ def predict_disease(self, image: np.ndarray):
129
  """Predict the disease from a preprocessed image and return detailed information."""
 
 
 
 
130
  try:
131
+ # Preprocess the input image for prediction
132
+ preprocessed_image = self.preprocess_image(image)
133
+ # Make a prediction using the disease detection model
134
  prediction = disease_model.predict(preprocessed_image)
135
+ # Get the predicted class index (the class with the highest probability)
136
  predicted_class = np.argmax(prediction, axis=1).item()
137
+ # Map the predicted class to the disease name, status, and recommendation
138
  disease_name = name_disease.get(predicted_class, "Unknown disease")
139
  disease_status = status_map.get(predicted_class, "Unknown status")
140
  recommendation = recommendations.get(predicted_class, "No recommendation available")
141
+ # Calculate the confidence of the prediction (as a percentage)
142
  confidence = prediction[0][predicted_class] * 100
143
  logger.info(f"Predicted: {disease_name} with {confidence:.2f}% confidence.")
144
 
145
+ # Generate a detailed response using Llama 3.2 for additional insights
146
  detailed_response = self.generate_detailed_response(disease_name, disease_status, recommendation)
147
  return detailed_response, disease_name, disease_status, recommendation, confidence
148
  except Exception as e:
149
+ # Log the error and return failure information
150
+ logger.error(f"Prediction error: {e}", exc_info=True)
151
  return "Prediction failed.", None, None, None, None
152
 
153
+ def generate_detailed_response(self, disease_name: str, status: str, recommendation: str) -> str:
154
  """Generate a detailed response using Llama 3.2 model for additional disease insights."""
155
+ # Construct a prompt for the Llama model with detailed information about the disease
156
  prompt = (
157
  f"The disease detected is {disease_name}, classified as {status}. "
158
  f"Recommended action: {recommendation}. "
159
  f"Here is more information about {disease_name}, including its causes, symptoms, and treatments "
160
  "for effective management on a poultry farm."
161
  )
162
+ # Generate a response using the Llama model based on the constructed prompt
163
  response = self.llama_response(prompt)
164
+ # Remove the prompt text from the response (if included) and return it
165
  return response.replace(prompt, "").strip()
166
 
167
+ def llama_response(self, prompt: str) -> str:
168
  """Generate a response from the Llama 3.2 model based on a given prompt."""
169
  try:
170
+ # Tokenize the prompt and prepare it for the Llama model
171
+ inputs = llama_tokenizer(prompt, return_tensors="tf", max_length=200, truncation=True, padding=True)
172
+ # Generate a response using the Llama model with sampling options for variety
173
+ outputs = llama_model.generate(inputs["input_ids"], max_length=200, do_sample=True, temperature=0.7, top_p=0.9)
174
+ # Decode the generated output to obtain the response text
175
  return llama_tokenizer.decode(outputs[0], skip_special_tokens=True)
176
  except Exception as e:
177
+ # Log the error and return an error message indicating failure
178
+ logger.error(f"Llama model response error: {e}", exc_info=True)
179
  return "Error generating detailed response."
180
 
181
+ def diagnose_and_respond(self, image: np.ndarray):
182
  """Diagnose the disease and respond with detailed information and recommendations."""
183
+ # Check if the provided image is valid (not None and has a non-zero size)
184
  if image is None or image.size == 0:
185
  return "Please provide a valid poultry fecal image.", None, None, None, None
186
+ # Predict the disease using the disease detection model and return the response
187
  return self.predict_disease(image)
188
 
189
  # Initialize the bot instance