Esempio n. 1
0
 def forecast_climate(self, entities):
     answer = []        
     # Entities were found
     #if (len(entities) > 0):
     # Get the localities
     geographic = self.catalog.get_Geographic()
     if geographic is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         ws_data = pd.DataFrame()
         # Try to search if locality was reconigzed
         if "locality" in entities.keys():                
             # This loop figure out all localtities through: states, municipalities and ws, which are into the message
             l = entities["locality"]
             ws_data = self.get_ws(l, geographic)
         
             # Check if the ws were found
             if(ws_data.shape[0] > 0):
                 ws_id = ws_data["ws_id"].unique()
                 ws = ','.join(ws_id)
                 # Ask for the forecast data
                 forecast = self.forecast.get_Climate(ws)
                 if forecast is None:
                     answer.append(NER(type = Error.ERROR_ACLIMATE_FORECAST_CLIMATE, tag = l))
                 else:
                     df = pd.merge(forecast, geographic, on='ws_id', how='inner')
                     answer.append(NER(Forecast.CLIMATE, df))
             else:
                 answer.append(NER(Error.LOCALITY_NOT_FOUND,tag=l))        
         else:
             answer.append(NER(Error.MISSING_GEOGRAPHIC))
     #else:
         #answer.append(NER(Error.MISSING_ENTITIES))
     return answer
Esempio n. 2
0
class PolicyManagement:

    def __init__(self, url):
        self.url_base = url        
        self.headers = {'Content-Type': 'application/json'}
        self.catalog = Catalog(url, self.headers)
        self.forecast = ForecastData(url, self.headers)
        self.historical_data = HistoricalData(url, self.headers)

    # Method that search geographic places
    # (dataframe) entities: List of entities found in the message user
    def geographic(self, entities):
        answer = []
        data = self.catalog.get_Geographic() 
        # Check if could connect with aclimate
        if data is None:
            answer.append(NER(Error.ERROR_ACLIMATE))
        else:
            # Entities weren't found
            if (len(entities) == 0):
                answer.append(NER(Geographic.STATE, data.loc[:,"state_name"].unique()))
            else:            
                # This section adds the list of localities  
                l = entities["locality"]                    
                e_data = data.loc[data["state_name"].str.contains(l.lower(), case = False), :]
                # Check if the message has state name in order to send the municipalities
                if(e_data.shape[0] > 0):
                    answer.append(NER(Geographic.MUNICIPALITIES_STATE, e_data.loc[:,"municipality_name"].unique(), l))
                else:
                    e_data = data.loc[data["municipality_name"].str.contains(l.lower(), case = False),: ]
                    # Check if message has municipality name in order to send weather stations
                    if(e_data.shape[0] > 0):
                        answer.append(NER(Geographic.WS_MUNICIPALITY, e_data.loc[:,"ws_name"].unique(),l))
                    else:
                        e_data = data.loc[data["ws_name"].str.contains(l.lower(), case = False),: ]
Esempio n. 3
0
 def historical_climatology(self, entities):
     answer = []        
     # Entities were found
     #if (len(entities) > 0):
     # Get the localities
     geographic = self.catalog.get_Geographic()
     if geographic is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         ws_data = pd.DataFrame()
         # Try to search if locality was reconigzed
         if "locality" in entities.keys():
             # This loop figure out all localtities through: states, municipalities and ws, which are into the message
             l = entities["locality"]
             ws_data = self.get_ws(l, geographic)
         
             # Check if the ws were found
             if ws_data.shape[0] > 0:
                 ws_id = ws_data["ws_id"].unique()
                 ws = ','.join(ws_id)
                 # Ask for the historical data
                 climatology = self.historical_data.get_Climatology(ws)
                 if climatology is None:
                     answer.append(NER(type = Error.ERROR_ACLIMATE_CLIMATOLOGY, tag = l))
                 else:
                     df = pd.merge(climatology, geographic, on='ws_id', how='inner')
                     # Filter by measure
                     if "measure" in entities.keys():                            
                         dft = pd.DataFrame()
                         dft = dft.append(df.loc[df["measure"] == self.get_measure_from_entities(entities["measure"]),:], ignore_index=True)
                         if(dft.shape[0] > 0):
                             df = dft
                     # Filter by months
                     if "date" in entities. keys():                            
                         m_n = self.get_month_from_entities(entities["date"])                                
                         if(len(m_n) >= 0):
                             m_n = m_n + 1
                             df = df.loc[df["month"].isin(m_n),:]
                     # Add all answers
                     answer.append(NER(Historical.CLIMATOLOGY, df, l))
             else:
                 answer.append(NER(Error.LOCALITY_NOT_FOUND,tag = l))  
         else:
             answer.append(NER(Error.MISSING_GEOGRAPHIC))
     #else:
         #answer.append(NER(Error.MISSING_ENTITIES))
     return answer
Esempio n. 4
0
 def cultivars(self, entities):
     answer = []
     data = self.catalog.get_Cultivars()
     if data is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         # Entities weren't found
         if (len(entities) == 0):
             answer.append(NER(Cultivars.CROP_MULTIPLE, data.loc[:,"cp_name"].unique()))
         # Entities were found
         else:
             # This section adds the list of cultivars for each crop required
             if "crop" in entities.keys():
                 c = entities["crop"]
                 e_data = data.loc[data["cp_name"].str.contains(c.lower(), case=False), :]
                 answer.append(NER(Cultivars.CROP_CULTIVAR, e_data.loc[:,"cu_name"].unique(), c))
             else:
Esempio n. 5
0
 def geographic(self, entities):
     answer = []
     data = self.catalog.get_Geographic() 
     # Check if could connect with aclimate
     if data is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         # Entities weren't found
         if (len(entities) == 0):
             answer.append(NER(Geographic.STATE, data.loc[:,"state_name"].unique()))
         else:            
             # This section adds the list of localities  
             l = entities["locality"]                    
             e_data = data.loc[data["state_name"].str.contains(l.lower(), case = False), :]
             # Check if the message has state name in order to send the municipalities
             if(e_data.shape[0] > 0):
                 answer.append(NER(Geographic.MUNICIPALITIES_STATE, e_data.loc[:,"municipality_name"].unique(), l))
             else:
                 e_data = data.loc[data["municipality_name"].str.contains(l.lower(), case = False),: ]
                 # Check if message has municipality name in order to send weather stations
                 if(e_data.shape[0] > 0):
Esempio n. 6
0
 def forecast_yield(self, entities, best_date = False):
     answer = []        
     # Entities were found
     #if (len(entities) > 0):            
     # Get the localities
     geographic = self.catalog.get_Geographic()
     cultivars = self.catalog.get_Cultivars()
     soils = self.catalog.get_Soils()
     if geographic is None or cultivars is None or soils is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         ws_data = pd.DataFrame()
         # Try to search if locality was reconigzed
         if "locality" in entities.keys():                
             # This loop figure out all localtities through: states, municipalities and ws, which are into the message
             l = entities["locality"]
             ws_data = self.get_ws(l, geographic)
         
             # Check if the ws were found
             if(ws_data.shape[0] > 0):
                 ws_id = ws_data["ws_id"].unique()
                 ws = ','.join(ws_id)
                 # Ask for the forecast data
                 forecast = self.forecast.get_Yield(ws)
                 if forecast is None:
                     answer.append(NER(type = Error.ERROR_ACLIMATE_FORECAST_YIELD, tag = l))
                 else:
                     df = pd.merge(forecast, geographic, on='ws_id', how='inner')
                     df = pd.merge(df, cultivars, on='cu_id', how='inner')
                     df = pd.merge(df, soils, on='so_id', how='inner')
                     # Filtering by cultivar
                     filter_cultivar = False
                     if "cultivar" in entities.keys():
                         cu = entities["cultivar"] 
                         dft = df.loc[df["cu_name"].str.contains(cu.lower(), case = False) ,:]
                         if(dft.shape[0] > 0):
                             df = dft
                             filter_cultivar = True
                     # Filter by crop if couldn't filter by cultivar
                     if(filter_cultivar == False and "crop" in entities.keys()):
                         cp = entities["crop"]
                         dft = df.loc[df["cp_name"].str.contains(cp.lower(), case = False) ,:]
                         if(dft.shape[0] > 0):
                             df = dft
                     # Filter by measure
                     df = df.loc[df["measure"].isin(["yield_14", "yield_0"]),:]
                     # Top five by crop 
                     crops = df["cp_name"].unique().tolist()
                     for c in crops:
                         amount = 5
                         type_answer = Forecast.YIELD_PERFORMANCE
                         dft = pd.DataFrame()
                         if best_date:
                             amount = 1
                             type_answer = Forecast.YIELD_DATE
                             stations = df["ws_id"].unique().tolist()
                             for s in stations:
                                 d_local = df.loc[df["cp_name"] == str(c) ,:]
                                 d_local = d_local.loc[ d_local["ws_id"] == str(s),:]
                                 dft = dft.append(d_local.nlargest(amount,"avg"), ignore_index = True)    
                         else:
                             dft = df.loc[df["cp_name"] == c,:].nlargest(amount,"avg")
                         answer.append(NER(type_answer, dft))
Esempio n. 7
0
             # This section adds the list of localities  
             l = entities["locality"]                    
             e_data = data.loc[data["state_name"].str.contains(l.lower(), case = False), :]
             # Check if the message has state name in order to send the municipalities
             if(e_data.shape[0] > 0):
                 answer.append(NER(Geographic.MUNICIPALITIES_STATE, e_data.loc[:,"municipality_name"].unique(), l))
             else:
                 e_data = data.loc[data["municipality_name"].str.contains(l.lower(), case = False),: ]
                 # Check if message has municipality name in order to send weather stations
                 if(e_data.shape[0] > 0):
                     answer.append(NER(Geographic.WS_MUNICIPALITY, e_data.loc[:,"ws_name"].unique(),l))
                 else:
                     e_data = data.loc[data["ws_name"].str.contains(l.lower(), case = False),: ]
                     # Check if message has weather station name in order to send the ws found
                     if(e_data.shape[0] > 0):
                         answer.append(NER(Geographic.WEATHER_STATION, e_data.loc[:,"ws_name"].unique(),l))
     return answer
 
 # Method that search cultivars available
 # (dataframe) entities: List of entities found in the message user
 def cultivars(self, entities):
     answer = []
     data = self.catalog.get_Cultivars()
     if data is None:
         answer.append(NER(Error.ERROR_ACLIMATE))
     else:
         # Entities weren't found
         if (len(entities) == 0):
             answer.append(NER(Cultivars.CROP_MULTIPLE, data.loc[:,"cp_name"].unique()))
         # Entities were found
         else:
Esempio n. 8
0
def api_query():
    
    # Validate autentication of melisa
    if not Melisa.objects(name=request.args.get("melisa")):
        return "ERROR 1"
    else:
        melisa = Melisa.objects.get(name=request.args.get("melisa"))

        if(melisa.token == request.args.get("token")):
            policy = PolicyManagement(aclimate)
            user = None
            user_id = request.args.get("user")
            message = request.args.get("message")
            chat_id = ""
            if request.args.get("chat_id"):
                chat_id = request.args.get("chat_id")
            # Check if user exists, otherwise it will create
            if not User.objects(user_id=user_id):
                user = User(melisa = melisa, user_id = user_id)
                user.save()
                request_body = {"user_id": user_id, "token": melisa.token, "chat_id":chat_id, "text": ["Hola, soy Melisa, un bot que provee información agroclimática."]}
                response = requests.post(melisa.url_post,json=request_body)
            else:
                user = User.objects.get(user_id=user_id)

            # Create chat
            chat = Chat(user = user, text = message, date = datetime.datetime.now(), ext_id = chat_id)
            chat.save()

            # message
            message = message.replace("_"," ")
            print(message)
            answer = []
            # Check some especial words
            if message.startswith(("hola", "hi", "Hola", "HOLA")) :
                answer.append(NER(Commands.HI))
                chat.intent_id = 6
                chat.intent_name = "hi"
                chat.slots = {}
                chat.save()            
            elif message.startswith(("bye", "adios", "Bye", "BYE", "ADIOS")):
                answer.append(NER(Commands.BYE))
                chat.intent_id = 7
                chat.intent_name = "bye"
                chat.slots = {}
                chat.save()
            elif message.startswith(("help","ayuda","Help", "HELP", "Ayuda", "Ayuda")):
                answer.append(NER(Commands.HELP))
                chat.intent_id = 8
                chat.intent_name = "help"
                chat.slots = {}
                chat.save()
            elif "thanks" in message or "gracias" in message:
                answer.append(NER(Commands.THANKS))
                chat.intent_id = 9
                chat.intent_name = "thanks"
                chat.slots = {}
                chat.save()
            else:
                # Temporal message
                rb_tmp = {"user_id": user_id, "token": melisa.token, "chat_id":chat_id, "text": ["Estoy procesando tu pregunta"]}
                response = requests.post(melisa.url_post,json=rb_tmp)
                # Decoded message
                utterance = nlu_o.nlu(message)
                print(utterance)
                # Update chat
                chat.intent_id = utterance["intent"]
                chat.intent_name = utterance["name"]
                chat.slots = utterance["slots"]
                chat.save()            

                intent = Intent(utterance["intent"])    
                entities = utterance["slots"]
                
                if(intent == Intent.PLACES):
                    answer = policy.geographic(entities)
                elif(intent == Intent.CULTIVARS):
                    answer = policy.cultivars(entities)
                elif(intent == Intent.CLIMATOLOGY):
                    answer = policy.historical_climatology(entities)
                elif(intent == Intent.FORECAST_PRECIPITATION):
                    answer = policy.forecast_climate(entities)
                elif(intent == Intent.FORECAST_YIELD):
                    answer = policy.forecast_yield(entities)
                elif(intent == Intent.FORECAST_DATE):
                    answer = policy.forecast_yield(entities, best_date=True)
            
            answers = Generator.print(answer)
            answers += ["En estos momentos estoy aprendiendo a responder a tus preguntas, por favor ayúdame a mejorar con esta encuesta: https://demeter.paperform.co/?4ctj8=" + str(chat.pk)]
            request_body = {"user_id": user_id, "token": melisa.token, "chat_id":chat_id, "text": answers}
            response = requests.post(melisa.url_post,json=request_body)
            return 'ok'
        else:
            return "ERROR 2"