File size: 9,895 Bytes
bb55334
 
 
 
 
aa7fdfd
 
c9fe7c4
 
aa7fdfd
bb55334
 
 
 
 
 
 
 
 
 
 
 
 
c9fe7c4
 
bb55334
 
 
 
 
c9fe7c4
 
 
 
 
 
aa7fdfd
 
 
 
 
 
 
c9fe7c4
 
bb55334
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8465b0
 
 
 
bb55334
 
 
51a6be5
bb55334
 
14b4ed5
 
 
bb55334
 
 
 
 
 
 
 
 
 
 
bd2dc88
aa7fdfd
 
 
bb55334
 
c9fe7c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82dca84
c9fe7c4
 
f3ceecb
14b4ed5
82dca84
 
 
f3ceecb
c9fe7c4
f3ceecb
 
 
82dca84
c9fe7c4
 
 
 
 
 
2b1a6e8
 
82dca84
 
c9fe7c4
82dca84
c9fe7c4
 
 
 
 
82dca84
 
 
c9fe7c4
f3ceecb
82dca84
c9fe7c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82dca84
 
 
 
 
 
 
 
 
 
 
 
 
 
bb55334
 
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
import json
import gradio as gr
from pathlib import Path
import os
import pandas as pd
import time
import random
from datetime import datetime
import pytz

import openai
from llama_index import GPTSimpleVectorIndex, SimpleDirectoryReader, LLMPredictor, ServiceContext
from langchain.chat_models import ChatOpenAI
import textwrap

# Procesar datos de PDF
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import CharacterTextSplitter

#import gradio as gr
from openai.embeddings_utils import get_embedding
from openai.embeddings_utils import cosine_similarity

from pymongo import MongoClient


# API KEY OPENAI
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

# DATABASE CONNECTION
CONNECTION = os.getenv("CONNECTION")
DATABASE = os.getenv("DATABASE")
COLLECTION = os.getenv("COLLECTION")


# CONSTANTES
DATASET_JSON = "demo-inmobiliaria.json"

# Ubicación dataset
carpeta_actual = os.getcwd()
print(f"Nombre de la carpeta actual: {carpeta_actual}")
PATH_FILE = f"{os.getcwd()}/{DATASET_JSON}"
print(f"Ubicación del archivo: {PATH_FILE}")


class ChatBotInmobiliaria():
    def __init__(self):
        self.embedding_engine = "text-embedding-ada-002"
        self.model_name = "gpt-3.5-turbo"
        self.index = None
    
    def create_dataset(self, directory_path, filepath_dataset):
        # directory_path: Directorio donde se ubican los archivos PDF.
        # filepath_dataset: Nombre del archivo JSON vectorizado.
        if directory_path != None:
            #Leer los PDFs
            pdf = SimpleDirectoryReader(directory_path).load_data()
            #Definir e instanciar el modelo
            modelo = LLMPredictor(llm=ChatOpenAI(temperature=0, model_name=self.model_name))
            #Indexar el contenido de los PDFs
            service_context = ServiceContext.from_defaults(llm_predictor=modelo)
            self.index = GPTSimpleVectorIndex.from_documents(pdf, service_context = service_context)
            self.__save_model(filepath_dataset)

    def __save_model(self, filepath):
        #Guardar el índice a disco para no tener que repetir cada vez
        #Recordar que necesistaríamos persistir el drive para que lo mantenga
        self.index.save_to_disk(filepath)
    
    def load_dataset(self, filepath):
        #Cargar el índice del disco
        self.index = GPTSimpleVectorIndex.load_from_disk(filepath)

    def ask(self, question=""):
        if len(question) == 0:
            print("Debe de ingresar una pregunta.")
        try:
            return str(self.index.query(f"Eres un agente inmobiliario virtual especializado en venta y alquiler de propiedades locales. Estoy aquí para ayudarte a encontrar la casa de tus sueños basado en tus preferencias y la legislación actual de Argentina. Por favor, proporciona tus preferencias y te mostraré algunas opciones que se ajusten a tus necesidades, teniendo en cuenta la legislación vigente. \
            Debes de responder la pregunta '```'{question}'```'.\
            Si la propiedad por la que pregunta si existe, entonces la frase con la que debes de responder debe tener el siguiente formato: El precio de venta o alquiler, la cantidad de ambientes o dormitorios, la superficie y la URL de una propiedad. La URL debe estar luego del texto 'Más información en '. \
            Si la propiedad por la que pregunta no existe, entonces debes de responder con la siguiente frase: 'Lo sentimos, no contamos con información para la propiedad solicitada. Sin embargo, puedes contactarnos vía telefónica al (011) 5368-5950 o en nuestra web https://www.oreilly.com.ar'."))
        except Exception as e:
            print(e)
            return "Hubo un error."
    

# Gradio
title = """
<p><center><h1>Demo Inmobiliaria</h1></p></center>
"""

description ="""
<p>
<center>
Demo Inmobiliaria, el objetivo es responder preguntas a través de OpenAI previamente entrenado con un archivo PDF.
<img src="https://raw.githubusercontent.com/All-Aideas/sea_apirest/main/logo.png" alt="logo" width="250"/>
</center>
</p>
"""

article = "<p style='text-align: center'><a href='http://allaideas.com/index.html' target='_blank'>Demo Inmobiliaria: Link para más info</a> </p>"
examples = [["¿Cuánto está una casa en San Isidro?"],["Hay precios más baratos?"],["A dónde llamo?"],["Qué leyes existen?"]]

gpt_bot = ChatBotInmobiliaria()
gpt_bot.load_dataset(PATH_FILE)


# Conexión a la base de datos MongoDB
client = MongoClient(CONNECTION)
db = client[DATABASE]
collection = db[COLLECTION]


def get_datetime():
    # Obtener la hora actual
    hora_actual = datetime.now()
    # Obtener la zona horaria de la hora actual
    zona_horaria_actual = pytz.timezone('America/Argentina/Buenos_Aires')
    # Aplicar la zona horaria a la hora actual
    hora_actual_con_zona_horaria = hora_actual.astimezone(zona_horaria_actual)
    return hora_actual_con_zona_horaria


def insert_chat(data):
    return collection.insert_one({"conversacion": data})


def update_chat(id, data):
    collection.update_one({"_id": id}, {"$set": {"conversacion": data}})


def add_chat_history(chat_history, message, answer, calificacion=None):
    global json_chat_history
    global id_chat

    json_chat = {"message": message, 
                 "answer": answer, 
                 "datetime": get_datetime(), 
                 "calificacion": calificacion}
    if len(chat_history) > 0:
        # Si chat_history no está vacía, significa que es una continuación de la conversación anterior
        json_chat_history.append(json_chat)
        # chat_history.append([message, answer])

        update_chat(id_chat, json_chat_history)
    else:
        # Si chat_history está vacía, es una nueva conversación
        json_chat_history = []
        json_chat_history.append(json_chat)
        # chat_history.append([message, answer])

        # Almacenar la nueva conversación en la base de datos
        db_result = insert_chat(json_chat_history)
        id_chat = db_result.inserted_id


with gr.Blocks() as demo:    
    gr.Markdown(f"""
    {title}
    {description}
    """)

    out1 = gr.Chatbot(label="Respuesta").style(height=300)
    
    with gr.Row():
        in2 = gr.Textbox(label="Pregunta")
        enter = gr.Button("Enviar mensaje")
    
    with gr.Row():
        upvote_btn = gr.Button(value="👍  Conforme", interactive=True)
        downvote_btn = gr.Button(value="👎  No conforme", interactive=True)
        flag_btn = gr.Button(value="⚠️  Alertar", interactive=True)
        # regenerate_btn = gr.Button(value="🔄  Regenerar", interactive=False)
    clear_btn = gr.Button(value="🗑️  Nuevo chat", interactive=True)

    ejemplos_gradio = gr.Examples(examples=examples, inputs=[in2, out1])
    gr.Markdown(article)


    def respond(message, chat_history):
        answer = str(gpt_bot.ask(question=message))
        add_chat_history(chat_history=chat_history, 
                    message=message, 
                    answer=answer)
        chat_history.append([message, answer])
        time.sleep(1)
        return "", chat_history


    enter.click(fn=respond, inputs=[in2, out1], outputs=[in2, out1])
    in2.submit(respond, [in2, out1], [in2, out1])


    def upvote_last_response(message, chat_history):
        """
        Obtener el último objeto JSON de la lista
        Actualizar el valor del atributo "calificacion"
        """
        if len(json_chat_history) > 0:
            json_chat_history[-1]["calificacion"] = "Conforme"
            update_chat(id_chat, json_chat_history)
        
        return message, chat_history


    def downvote_last_response(message, chat_history):
        """
        Obtener el último objeto JSON de la lista
        Actualizar el valor del atributo "calificacion"
        """
        if len(json_chat_history) > 0:
            json_chat_history[-1]["calificacion"] = "No conforme"
            update_chat(id_chat, json_chat_history)
        
        return message, chat_history
    
    def flag_last_response(message, chat_history):
        """
        Obtener el último objeto JSON de la lista
        Actualizar el valor del atributo "calificacion"
        """
        if len(json_chat_history) > 0:
            json_chat_history[-1]["calificacion"] = "Alertar"
            update_chat(id_chat, json_chat_history)
        
        return message, chat_history


    # def regenerate_answer(message, chat_history):
    #     """
    #     Obtener el último objeto JSON de la lista
    #     Actualizar el valor del atributo "calificacion"
    #     """
    #     if len(json_chat_history) > 0:
    #         pregunta = json_chat_history[-1]["message"]
    #         answer = str(gpt_bot.ask(question=pregunta))
    #         add_chat_history(chat_history=chat_history, 
    #                          message=pregunta, 
    #                          answer=answer,
    #                          calificacion="Regenerado")
    #         chat_history.pop(-1)
    #         chat_history.append([message, answer])
    #         time.sleep(1)        
    #     return message, chat_history


    upvote_btn.click(upvote_last_response, inputs=[in2, out1], outputs=[in2, out1])
    downvote_btn.click(downvote_last_response, inputs=[in2, out1], outputs=[in2, out1])
    flag_btn.click(flag_last_response, inputs=[in2, out1], outputs=[in2, out1])
    # regenerate_btn.click(regenerate_answer, inputs=[in2, out1], outputs=[in2, out1])
    clear_btn.click(lambda: None, None, out1, queue=False)

    
# in1 = gr.inputs.Textbox(label="Pregunta")
# out1 = gr.outputs.Chatbot(label="Respuesta").style(height=350)

# demo = gr.Interface(
#     fn=chat,
#     inputs=in1,
#     outputs=out1,
#     title="Demo Inmobiliaria",
#     description=description,
#     article=article,
#     enable_queue=True,
#     examples=examples,
#     )

demo.launch(debug=True)