from flask import Flask, request from twilio.twiml.messaging_response import MessagingResponse from twilio.rest import Client import os import shutil from bs4 import BeautifulSoup import requests from requests.auth import HTTPBasicAuth from PIL import Image from io import BytesIO import pandas as pd from urllib.parse import urlparse from pypdf import PdfReader from ai71 import AI71 import uuid from inference_sdk import InferenceHTTPClient import base64 app = Flask(__name__) UPLOAD_FOLDER = '/code/uploads' if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER class ConversationBufferMemory: def __init__(self, max_size): self.memory = [] self.max_size = max_size def add_to_memory(self, interaction): self.memory.append(interaction) if len(self.memory) > self.max_size: self.memory.pop(0) def get_memory(self): return self.memory conversation_memory = ConversationBufferMemory(max_size=2) account_sid = os.environ.get('TWILIO_ACCOUNT_SID') auth_token = os.environ.get('TWILIO_AUTH_TOKEN') client = Client(account_sid, auth_token) from_whatsapp_number = 'whatsapp:+14155238886' PROMPT_TEMPLATE = """ Answer the question based only on the following context: {context} --- Answer the question based on the above context: {question} """ AI71_API_KEY = os.environ.get('AI71_API_KEY') def generate_response(query, chat_history): response = '' for chunk in AI71(AI71_API_KEY).chat.completions.create( model="tiiuae/falcon-180b-chat", messages=[ {"role": "system", "content": "You are the best agricultural assistant. Remember to give a response in not more than 2 sentences. Greet the user if the user greets you."}, {"role": "user", "content": f'''Answer the query based on history {chat_history}: {query}'''}, ], stream=True, ): if chunk.choices[0].delta.content: response += chunk.choices[0].delta.content return response.replace("###", '').replace('\nUser:', '') def predict_pest(filepath): CLIENT = InferenceHTTPClient( api_url="https://detect.roboflow.com", api_key="oF1aC4b1FBCDtK8CoKx7" ) result = CLIENT.infer(filepath, model_id="pest-detection-ueoco/1") return result['predictions'][0] def predict_disease(filepath): CLIENT = InferenceHTTPClient( api_url="https://classify.roboflow.com", api_key="oF1aC4b1FBCDtK8CoKx7" ) result = CLIENT.infer(filepath, model_id="plant-disease-detection-iefbi/1") return result['predicted_classes'][0] def convert_img(url, account_sid, auth_token): try: response = requests.get(url, auth=HTTPBasicAuth(account_sid, auth_token)) response.raise_for_status() parsed_url = urlparse(url) media_id = parsed_url.path.split('/')[-1] filename = f"downloaded_media_{media_id}" media_filepath = os.path.join(UPLOAD_FOLDER, filename) with open(media_filepath, 'wb') as file: file.write(response.content) print(f"Media downloaded successfully and saved as {media_filepath}") with open(media_filepath, 'rb') as img_file: image = Image.open(img_file) converted_filename = f"image.jpg" converted_filepath = os.path.join(UPLOAD_FOLDER, converted_filename) image.convert('RGB').save(converted_filepath, 'JPEG') return converted_filepath except requests.exceptions.HTTPError as err: print(f"HTTP error occurred: {err}") except Exception as err: print(f"An error occurred: {err}") def get_weather(city): city = city.strip().replace(' ', '+') r = requests.get(f'https://www.google.com/search?q=weather+in+{city}') soup = BeautifulSoup(r.text, 'html.parser') temperature = soup.find('div', attrs={'class': 'BNeawe iBp4i AP7Wnd'}).text return temperature from zenrows import ZenRowsClient Zenrow_api = os.environ.get('Zenrow_api') zenrows_client = ZenRowsClient(Zenrow_api) def get_rates(): url = "https://www.kisandeals.com/mandiprices/ALL/TAMIL-NADU/ALL" response = zenrows_client.get(url) if response.status_code == 200: soup = BeautifulSoup(response.content, 'html.parser') rows = soup.select('table tbody tr') data = {} for row in rows: columns = row.find_all('td') if len(columns) >= 2: commodity = columns[0].get_text(strip=True) price = columns[1].get_text(strip=True) if '₹' in price: data[commodity] = price return str(data) + " These are the prices for 1 kg" def get_news(): news = [] url = "https://economictimes.indiatimes.com/news/economy/agriculture?from=mdr" response = zenrows_client.get(url) if response.status_code == 200: soup = BeautifulSoup(response.content, 'html.parser') headlines = soup.find_all("div", class_="eachStory") for story in headlines: headline = story.find('h3').text.strip() news.append(headline) return news def download_and_save_as_txt(url, account_sid, auth_token): try: response = requests.get(url, auth=HTTPBasicAuth(account_sid, auth_token)) response.raise_for_status() parsed_url = urlparse(url) media_id = parsed_url.path.split('/')[-1] filename = f"pdf_file.pdf" txt_filepath = os.path.join(UPLOAD_FOLDER, filename) with open(txt_filepath, 'wb') as file: file.write(response.content) print(f"Media downloaded successfully and saved as {txt_filepath}") return txt_filepath except requests.exceptions.HTTPError as err: print(f"HTTP error occurred: {err}") except Exception as err: print(f"An error occurred: {err}") def download_file(url, extension): try: response = requests.get(url) response.raise_for_status() filename = f"{uuid.uuid4()}{extension}" file_path = os.path.join(UPLOAD_FOLDER, filename) with open(file_path, 'wb') as file: file.write(response.content) print(f"File downloaded and saved as {file_path}") return file_path except requests.exceptions.HTTPError as err: print(f"HTTP error occurred: {err}") except Exception as err: print(f"An error occurred: {err}") return None @app.route('/whatsapp', methods=['POST']) def whatsapp_webhook(): incoming_msg = request.values.get('Body', '').lower() sender = request.values.get('From') num_media = int(request.values.get('NumMedia', 0)) chat_history = conversation_memory.get_memory() if num_media > 0: media_url = request.values.get('MediaUrl0') content_type = request.values.get('MediaContentType0') if content_type.startswith('image/'): # Handle image processing (disease/pest detection) filepath = convert_img(media_url, account_sid, auth_token) response_text = handle_image(filepath) else: # Handle PDF processing filepath = download_and_save_as_txt(media_url, account_sid, auth_token) response_text = process_and_query_pdf(filepath) elif ('weather' in incoming_msg.lower()) or ('climate' in incoming_msg.lower()) or ( 'temperature' in incoming_msg.lower()): response_text = get_weather(incoming_msg.lower()) elif 'bookkeeping' in incoming_msg: response_text = "Please provide the details you'd like to record." elif ('rates' in incoming_msg.lower()) or ('price' in incoming_msg.lower()) or ( 'market' in incoming_msg.lower()) or ('rate' in incoming_msg.lower()) or ('prices' in incoming_msg.lower()): rates = get_rates() response_text = generate_response(incoming_msg + ' data is ' + rates, chat_history) elif ('news' in incoming_msg.lower()) or ('information' in incoming_msg.lower()): news = get_news() response_text = generate_response(incoming_msg + ' data is ' + str(news), chat_history) else: response_text = generate_response(incoming_msg, chat_history) conversation_memory.add_to_memory({"user": incoming_msg, "assistant": response_text}) send_message(sender, response_text) return '', 204 def handle_image(filepath): try: disease = predict_disease(filepath) except: disease = None try: pest = predict_pest(filepath) except: pest = None if disease: response_text = f"Detected disease: {disease}" disease_info = generate_response(f"Provide brief information about {disease} in agriculture", "") response_text += "\n" + disease_info elif pest: response_text = f"Detected pest: {pest}" pest_info = generate_response(f"Provide brief information about {pest} in agriculture", "") response_text += "\n" + pest_info else: response_text = "Sorry, I couldn't detect any disease or pest. Please try another image." return response_text def process_and_query_pdf(filepath): # Read and process the PDF reader = PdfReader(filepath) text = '' for page in reader.pages: text += page.extract_text() if not text: return "Sorry, the PDF content could not be extracted." # Generate response based on extracted PDF content response_text = generate_response(f"The PDF content is {text}", "") return response_text def send_message(recipient, message): client.messages.create( body=message, from_=from_whatsapp_number, to=recipient ) def send_initial_message(to_number): send_message( f'whatsapp:{to_number}', 'Welcome to the Agri AI Chatbot! How can I assist you today? You can send an image with "pest" or "disease" to classify it.' ) if __name__ == "__main__": send_initial_message('919080522395') send_initial_message('916382792828') app.run(host='0.0.0.0', port=7860)