File size: 7,926 Bytes
20c2b8b
 
 
 
 
 
 
 
 
 
 
 
 
f7ecfca
 
 
20c2b8b
 
e38f553
20c2b8b
f7ecfca
 
c47c3f4
6847bae
 
 
 
f7ecfca
2efd879
0810453
20c2b8b
29d2476
20c2b8b
 
 
 
68c609f
20c2b8b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68c609f
 
 
20c2b8b
 
 
 
 
 
 
 
f7ecfca
 
 
1830b50
 
f7ecfca
 
 
 
 
 
 
 
 
20c2b8b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f7ecfca
3b722d7
f7ecfca
20c2b8b
 
 
 
 
 
 
 
 
476a42a
20c2b8b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import pandas as pd
import openai
import re
import json 
from langchain.chat_models import ChatOpenAI
import regex
import gradio as gr
from langchain.schema import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from openai.embeddings_utils import get_embedding
from openai.embeddings_utils import cosine_similarity
import gspread # See: https://docs.gspread.org/en/v5.10.0/user-guide.html
from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime

# API de OpenAI
openai.api_key = os.getenv("OPENAI_API_KEY")

# Establece las credenciales y la API

credentials = os.getenv( "credentials" )

credentials =  json.loads( credentials )

gc = gspread.service_account_from_dict( credentials )

Google_URL = os.getenv( "Google_URL" )

# Cargar el archivo 
df_Normas_Embeddings = pd.read_csv( os.getenv( "Data" ) )

# Main OpenAI Function
#
def get_completion_from_messages( messages, model = "gpt-3.5-turbo-16k", 
                                  temperature = 0, max_tokens = 4500 ): ##Check max_tokens 
    response = openai.ChatCompletion.create(
               model = model,
               messages = messages,
               temperature = temperature, 
               max_tokens = max_tokens, 
    )
    return response.choices[0].message["content"]

# Get LEY
#
def get_topic( user_message ):
    #
    delimiter = "####"
    system_message = f"""
    Eres un especialista en temas fiscales en México. \
    Se le proporcionarán consultas o preguntas respecto de temas fiscales. \
    Las consultas o preguntas se delimitarán con los caracteres {delimiter}.

    Las consultas serán sobre diferentes Leyes, Códigos Federales y normativas como:
    1. La LEY DEL IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS y el REGLAMENTO DE LA LEY DEL \
    IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS
    2. La LEY DEL IMPUESTO SOBRE LA RENTA y el REGLAMENTO DE LA LEY DEL IMPUESTO SOBRE LA RENTA
    3. La LEY DEL IMPUESTO AL VALOR AGREGADO y el REGLAMENTO DE LA LEY DEL IMPUESTO AL VALOR AGREGADO

    Proporciona una lista de objetos de python, donde cada objeto sea alguno de: \
    'IMPUESTO AL VALOR AGREGADO', 'IMPUESTO SOBRE LA RENTA', o 'IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS'.

    Donde el tema se debe encontrar en la consulta o pregunta relacionada con temas fiscales.

    Solo proporciona la lista de objetos, nada más.
    """
    #
    messages =  [  
    {'role':'system', 
     'content': system_message},    
    {'role':'user', 
     'content': f"{delimiter}{user_message}{delimiter}"},  
    ] 
    return get_completion_from_messages( messages )

# Function: Get embeddings

def get_embedding( text , model ):
    text = text.replace("\n", " ")
    return openai.Embedding.create( input = [text], model = model )['data'][0]['embedding']

# Función de búsqueda

def buscar( busqueda, datos, n_resultados):
    #
    busqueda_embed = get_embedding( busqueda, model = "text-embedding-ada-002" )
    datos['Similitud'] = datos['Embedding'].apply( lambda x: cosine_similarity( eval( x ) , busqueda_embed ) )
    datos = datos.sort_values('Similitud', ascending = False )
    #
    return datos.iloc[:n_resultados][['Tema', 'Norma', 'Textos', 'NumPalabras', 'Embedding', 'Similitud']]

#
def get_respuesta( user_message, informacion ):
    #
    delimiter = "####"
    system_message = f"""
    Eres un especialista en temas fiscales en México. \
    Se le proporcionarán consultas o preguntas respecto de temas fiscales. \
    Las consultas o preguntas e información para responder se delimitarán \
    con los caracteres {delimiter}.
    
    La información que se te proporcionará para responder las consultas o preguntas \
    estará en una lista de Python.
    
    La información corresponde a extractos de Leyes, Códigos Federales y normativas como:
    1. La LEY DEL IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS y el REGLAMENTO DE LA LEY DEL \
    IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS.
    2. La LEY DEL IMPUESTO SOBRE LA RENTA y el REGLAMENTO DE LA LEY DEL IMPUESTO SOBRE LA RENTA.
    3. La LEY DEL IMPUESTO AL VALOR AGREGADO y el REGLAMENTO DE LA LEY DEL IMPUESTO AL VALOR AGREGADO.
    4. El CÓDIGO FISCAL DE LA FEDERACIÓN y el REGLAMENTO DEL CÓDIGO FISCAL DE LA FEDERACIÓN.
    
    La información se te proporcionará con la siguiente estructura: Nombre de la Ley, Código o \
    Reglamento, seguido del Artículo y el texto del Artículo.
    
    Asegúrate de realizar preguntas de seguimiento. 
    """
    #
    messages =  [  
    {'role':'system',
     'content': system_message},   
    {'role':'user',
     'content': f"""
    {delimiter} 
    Usa exclusivamente la información contenida en la siguiente lista: 
    {informacion} 
    para responder sin límite de palabras lo siguiente: {user_message}
    En tu respuesta menciona el Nombre de la Ley, Código o Reglamento de donde proviene la información \
    incluida en tu respuesta.
    Responde de forma detallada.
    {delimiter}
    """},   
    ]
    #
    return get_completion_from_messages(messages)
    #

    #

#
def update_records( user_message ):
    #
    sht = gc.open_by_url(Google_URL)
    #
    sht.sheet1.get_all_records()
    #
    sht.sheet1.update_cell( len( sht.sheet1.get_all_records()[:] ) + 2 , 
                            1 , datetime.now().strftime("%m/%d/%Y, %H:%M:%S") )
    #
    sht.sheet1.update_cell( len( sht.sheet1.get_all_records()[:] ) + 1 , 
                            2 , user_message )
#
def Chat( user_message_1 ):
    #
    norma_y_tema_response_1 = get_topic( user_message_1 )
    norma_y_tema_response_1 = eval(norma_y_tema_response_1) 
    norma_y_tema_response_1.append( 'Todos' )
    #
    df_datos = df_Normas_Embeddings[ df_Normas_Embeddings['Tema'].isin(norma_y_tema_response_1) ]
    #
    df_final = buscar( user_message_1, df_datos, 10).reset_index( drop = True)
    #
    df_final['Cum_NumPalabras'] = df_final['NumPalabras'].cumsum()
    #
    df_final = df_final[ df_final['Cum_NumPalabras'] <= 1400 ]
    #
    df_final[ 'Final_Text' ] = df_final[ 'Norma' ] + ', ' + df_final[ 'Textos' ]
    #
    Textos = df_final[ 'Final_Text' ].tolist()
    #
    # Save Question and date time
    update_records( user_message_1 )
    #
    return get_respuesta( user_message_1, Textos ), '\n'.join(Textos)


# 
# 
with gr.Blocks() as demo:
    #
    gr.Markdown("App basada en servicios (Embeddings) de OpenAI (Chat GPT-3.5)")
    gr.Markdown("Este es un producto de prueba desarrollado por Analítica Boutique, S.C.")
    gr.Markdown("Contacto: vicente@analiticaboutique.com.mx")
    gr.Markdown("La base de información de este ChatBot es:\
                 1. La LEY DEL IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS y el \
                    REGLAMENTO DE LA LEY DEL IMPUESTO ESPECIAL SOBRE PRODUCCIÓN Y SERVICIOS. \n\
                 2. La LEY DEL IMPUESTO SOBRE LA RENTA y el REGLAMENTO DE LA LEY DEL IMPUESTO \
                    SOBRE LA RENTA. \n\
                 3. La LEY DEL IMPUESTO AL VALOR AGREGADO y el REGLAMENTO DE LA LEY DEL IMPUESTO \
                    AL VALOR AGREGADO. \n\
                 4. El CÓDIGO FISCAL DE LA FEDERACIÓN y el REGLAMENTO DEL CÓDIGO FISCAL DE LA \
                    FEDERACIÓN.")
    busqueda = gr.Textbox(label = "Escribe la pregunta o tarea para iniciar la conversación.")
    greet_btn = gr.Button("Preguntar")
    # Crear dos widgets de salida en lugar de uno
    output1 = gr.Textbox(label = "Mi propuesta de respuesta:")
    output2 = gr.Textbox(label = "Los extractos de las Leyes, Reglamentos y Código que usé:")

    # Modificar la función click para asignar cada parte de la tupla a un widget diferente
    greet_btn.click(fn=Chat, inputs=[busqueda], outputs=[output1, output2])
    #
#demo.launch( share = True )
demo.launch( )
#
#