File size: 10,170 Bytes
940c98a
5dff670
 
052e52f
5dff670
 
979aaae
 
 
 
 
 
 
 
 
 
96fe0c0
979aaae
 
f4738b1
940c98a
5dff670
 
 
 
 
 
940c98a
aefdf99
 
 
 
5dff670
aefdf99
 
 
 
 
 
 
5dff670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4738b1
 
 
5dff670
f4738b1
 
5dff670
 
f4738b1
5dff670
 
 
 
 
 
 
 
 
 
 
 
 
f4738b1
 
5dff670
 
 
 
 
 
 
f4738b1
5dff670
f85bc8f
5dff670
 
 
 
 
 
 
 
 
 
f85bc8f
5dff670
f85bc8f
5dff670
 
f85bc8f
5dff670
 
 
 
940c98a
5dff670
 
 
 
940c98a
5dff670
 
 
 
 
 
f4738b1
5dff670
 
 
f4738b1
5dff670
 
 
f4738b1
5dff670
 
 
 
 
 
 
 
 
 
 
 
f4738b1
5dff670
 
 
 
 
 
 
 
 
 
 
 
 
 
f4738b1
5dff670
 
907d1ed
5dff670
 
 
907d1ed
5dff670
 
 
f4738b1
5dff670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
907d1ed
5dff670
 
 
 
 
0fd9053
558f5d1
 
052e52f
558f5d1
 
 
5dff670
f4738b1
558f5d1
 
 
a8f0234
5dff670
 
 
 
1d239e0
5dff670
 
 
 
 
 
 
 
 
 
 
 
 
 
 
558f5d1
979aaae
558f5d1
5dff670
c36a14b
 
fa7d405
5dff670
 
 
 
 
 
 
 
 
 
 
 
979aaae
 
5dff670
 
979aaae
 
5dff670
979aaae
 
5dff670
 
 
979aaae
 
 
 
 
 
 
 
 
 
 
 
5dff670
979aaae
 
 
 
 
 
d3d3acb
 
 
 
 
05b09c6
691414c
1a1cf31
c36a14b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
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)