JoseAntonioBarrancoBernabe commited on
Commit
d5f44d7
1 Parent(s): 0b7778d

modificación para keys

Browse files
Files changed (1) hide show
  1. app.py +258 -254
app.py CHANGED
@@ -1,254 +1,258 @@
1
-
2
- ##Instalación de paquetes necesarios
3
- import streamlit as st
4
- import os
5
- import time
6
- import torch
7
- from utils import *
8
- from dotenv import load_dotenv
9
- load_dotenv()
10
-
11
- ##import nest_asyncio
12
- ##nest_asyncio.apply()
13
- from llama_parse import LlamaParse
14
-
15
- from llama_index.llms.openai import OpenAI
16
- from llama_index.embeddings.openai import OpenAIEmbedding
17
- from llama_index.core import VectorStoreIndex, ServiceContext
18
- from llama_index.core import SimpleDirectoryReader
19
- from llama_index.core import Settings
20
- print(torch.cuda.is_available())
21
- ######
22
-
23
- ## titulos y cabeceras
24
- st.set_page_config('compare PDF por LLM')
25
- st.title("Comparar PDFs mediante LLM")
26
- st.subheader("Campos a comparar en tu PDF",divider='rainbow')
27
-
28
- #### Inicializar mensajes de chat
29
- if "messages" not in st.session_state.keys():
30
- st.session_state.messages = [
31
- {"role": "assistant", "content": "Ask me a question about PDFs files you provided me"}
32
- ]
33
-
34
- @st.cache_resource(show_spinner=False) # Añade decorador de caché
35
- def cargar_embedmodel_y_llmmodel():
36
- return True
37
-
38
- #esta variable es para tener aqui un listado de aquellos ficheros que se han ido subiendo
39
- archivos = []
40
-
41
- ## carga y almacenamiento de ficheros almacenada, acepta varios.
42
- with st.sidebar:
43
- archivos = load_name_files(FILE_LIST)
44
- files_uploaded = st.file_uploader(
45
- "Carga tus ficheros PDF",
46
- type="pdf",
47
- accept_multiple_files=True,
48
- on_change=st.cache_resource.clear
49
- )
50
-
51
- if st.button("Guardar y procesar por LLM", type="secondary",help="donde buscará lo que comparará"):
52
- for pdf in files_uploaded:
53
- if pdf is not None and pdf.name not in archivos:
54
- archivos.append(pdf.name)
55
-
56
- archivos = save_name_files(FILE_LIST, archivos)
57
-
58
-
59
- if len(archivos)>0:
60
- st.write('Los archivos PDF se han cargados:')
61
- lista_documentos = st.empty()
62
- with lista_documentos.container():
63
- for arch in archivos:
64
- st.write(arch)
65
- if st.button('Borrar ficheros'):
66
- archivos = []
67
- clean_files(FILE_LIST)
68
- lista_documentos.empty()
69
-
70
-
71
- # comprueba que hay archivos a ser tratados
72
- if len(archivos)>0:
73
- # comprueba que hay consulta a responder
74
- if user_question := st.chat_input("Realizar consulta:"):
75
- st.session_state.messages.append({"role": "user", "content": user_question})
76
-
77
- if user_question:
78
- for message in st.session_state.messages: # Muestra anteriores mensajes
79
- with st.chat_message(message["role"]):
80
- st.write(message["content"])
81
-
82
- alert = st.warning("Sea paciente") # Mensaje de aviso o warning al usuario
83
- time.sleep(3) # establece tiempo espera en 3 segundos
84
- alert.empty() # borra el aviso
85
-
86
- # se define el analizador-parser de los documentos.
87
- parser = LlamaParse(
88
- api_key=os.environ["LLAMA_CLOUD_API_KEY"], ##API de acceso a Cloud de LlamaIndex
89
- result_type="markdown", # se toma "markdown", tambien hay text disponible
90
- verbose=True,
91
- )
92
-
93
- cargar_embedmodel_y_llmmodel()
94
-
95
- #se parametrizan los modelos de embedding y LLM
96
- embed_model=OpenAIEmbedding(model="text-embedding-3-small") #embeddings para base de conocimiento
97
- llm = OpenAI(model="gpt-3.5-turbo-0125") #modelo LLM usado
98
-
99
- Settings.llm = llm
100
- Settings.embed_model = embed_model
101
-
102
-
103
- tratar = load_name_files(FILE_LIST) ##variable que tomará los ficheros a tratar recuperados de funcion
104
- # st.write(tratar[0]) # se puede desasteriscar en desarrollo para apoyo
105
- # st.write(tratar[1]) # se puede desasteriscar en desarrollo para apoyo
106
-
107
-
108
- # Carga de los ficheros mediante LlamaParse, se ejecutará job para cada analizador-parser de los mismos
109
- docs_202401 = parser.load_data( f'{tratar[0]}')
110
- docs_202402 = parser.load_data( f'{tratar[1]}')
111
-
112
- #uso de MarkdownElementNodeParser para analizar la salida de LlamaParse mediante un motor de consultas de recuperación(recursivo)
113
- from llama_index.core.node_parser import MarkdownElementNodeParser
114
- node_parser = MarkdownElementNodeParser(llm=OpenAI(model="gpt-3.5-turbo-0125"), num_workers=8)
115
-
116
- import pickle
117
- from llama_index.postprocessor.flag_embedding_reranker import FlagEmbeddingReranker
118
- # se parametriza el modelo reranker
119
- reranker = FlagEmbeddingReranker(
120
- top_n=5,
121
- model="BAAI/bge-reranker-large",
122
- )
123
- #funcion para Facilitar el motor de consultas sobre el almacén de vectores, y poderse realizar la recuperación.
124
- def create_query_engine_over_doc(docs, nodes_save_path=None):
125
- """Big function to go from document path -> recursive retriever."""
126
- if nodes_save_path is not None and os.path.exists(nodes_save_path):
127
- raw_nodes = pickle.load(open(nodes_save_path, "rb"))
128
- else:
129
- raw_nodes = node_parser.get_nodes_from_documents(docs)
130
- if nodes_save_path is not None:
131
- pickle.dump(raw_nodes, open(nodes_save_path, "wb"))
132
-
133
- base_nodes, objects = node_parser.get_nodes_and_objects(
134
- raw_nodes
135
- )
136
-
137
- ### Recuperador-retriever
138
- # indice y motor
139
- vector_index = VectorStoreIndex(nodes=base_nodes+objects)
140
- query_engine = vector_index.as_query_engine(
141
- similarity_top_k=15,
142
- node_postprocessors=[reranker]
143
- )
144
- return query_engine, base_nodes, vector_index ###devuelve motor de consultas y nodos
145
-
146
- ## motores de consulta y nodos para cada documento usando la función anterior.
147
- ## En los ficheros .pkl se puede ver la estructura de los documentos que ha conformado o analizado y será con la que trabajará.
148
- query_engine_202401, nodes_202401,vindex1 = create_query_engine_over_doc(
149
- docs_202401, nodes_save_path="202401_nodes.pkl"
150
- )
151
- query_engine_202402, nodes_202402,vindex2 = create_query_engine_over_doc(
152
- docs_202402, nodes_save_path="202402_nodes.pkl"
153
- )
154
-
155
- from llama_index.core.tools import QueryEngineTool, ToolMetadata
156
- from llama_index.core.query_engine import SubQuestionQueryEngine
157
-
158
- from llama_index.core.llms import ChatMessage
159
-
160
- # motor de consulta como tool, configuración y contexto de los datos que deberá proveer por los que será consultado
161
- # debajo se usa como motor de subconsultas SubQuestionQueryEngine
162
- query_engine_tools = [
163
- QueryEngineTool(
164
- query_engine=query_engine_202401,
165
- metadata=ToolMetadata(
166
- name="pdf_ENERO",
167
- description=(
168
- # "Provides information about Datos del Producto for ENERO"
169
- # "Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases, Usos y Dosis Autorizados,Plazos de Seguridad"
170
- """\
171
- The documents provided are plant protection product data sheets in PDF format.
172
- Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases,
173
- Usos y Dosis Autorizados,Plazos de Seguridad:
174
- # Datos del Producto
175
- |Numero de Registro|
176
- |Estado|
177
- |Fechas Inscripción|
178
- |Renovación|
179
- |Caducidad|
180
- |Nombre Comercial|
181
-
182
- # Titular
183
-
184
- # Fabricante
185
-
186
- # Composición
187
-
188
- # Envases
189
-
190
- # Usos y Dosis Autorizados
191
- |USO|
192
- |AGENTE|
193
- |Dosis|
194
- |Condic. Especifico|
195
-
196
- """
197
- ),
198
- ),
199
- ),
200
- QueryEngineTool(
201
- query_engine=query_engine_202402,
202
- metadata=ToolMetadata(
203
- name="pdf_FEBRERO",
204
- description=(
205
- # "Provides information about Datos del Producto for FEBRERO"
206
- # "Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases, Usos y Dosis Autorizados,Plazos de Seguridad"
207
- """\
208
- The documents provided are plant protection product data sheets in PDF format.
209
- Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases,
210
- Usos y Dosis Autorizados,Plazos de Seguridad:
211
- # Datos del Producto
212
- |Numero de Registro|
213
- |Estado|
214
- |Fechas Inscripción|
215
- |Renovación|
216
- |Caducidad|
217
- |Nombre Comercial|
218
-
219
- # Titular
220
-
221
- # Fabricante
222
-
223
- # Composición
224
-
225
- # Envases
226
-
227
- # Usos y Dosis Autorizados
228
- |USO|
229
- |AGENTE|
230
- |Dosis|
231
- |Condic. Especifico|
232
-
233
- """
234
- ),
235
- ),
236
- ),
237
- ]
238
- # subconsultas con tool creada a través de SubQuestionQueryEngine
239
- sub_query_engine = SubQuestionQueryEngine.from_defaults(
240
- query_engine_tools=query_engine_tools,
241
- llm=llm
242
- )
243
-
244
- if "chat_engine" not in st.session_state.keys(): # Initializa motor chat
245
- # para que generen las subconsultas con la consulta-query del usuario
246
- streaming_response = sub_query_engine.query(user_question)
247
-
248
- ## If last message is not from assistant, generate a new response
249
- if st.session_state.messages[-1]["role"] != "assistant":
250
- with st.chat_message("assistant"):
251
- with st.spinner("Thinking..."): #figura del spinner de streamlit mientras se ejecuta bloque
252
- response = st.write(streaming_response.response) #respuesta entregada a la query-consulta del usuario
253
- st.session_state.messages.append({"role": "assistant", "content": response})
254
-
 
 
 
 
 
1
+
2
+ ##Instalación de paquetes necesarios
3
+ import streamlit as st
4
+ import os
5
+ import time
6
+ import torch
7
+ from utils import *
8
+ from dotenv import load_dotenv
9
+ load_dotenv()
10
+
11
+ ##import nest_asyncio
12
+ ##nest_asyncio.apply()
13
+ from llama_parse import LlamaParse
14
+
15
+ from llama_index.llms.openai import OpenAI
16
+ from llama_index.embeddings.openai import OpenAIEmbedding
17
+ from llama_index.core import VectorStoreIndex, ServiceContext
18
+ from llama_index.core import SimpleDirectoryReader
19
+ from llama_index.core import Settings
20
+ ######
21
+
22
+ ## titulos y cabeceras
23
+ st.set_page_config('compare PDF por LLM')
24
+ st.title("Comparar PDFs mediante LLM")
25
+ st.subheader("Campos a comparar en tu PDF",divider='rainbow')
26
+
27
+ OPENAI_API_KEY = st.text_input('OpenAI API Key', type='password')
28
+ LLAMA_CLOUD_API_KEY = st.text_input('LLAMA API Key', type='password')
29
+
30
+ #### Inicializar mensajes de chat
31
+ if "messages" not in st.session_state.keys():
32
+ st.session_state.messages = [
33
+ {"role": "assistant", "content": "Ask me a question about PDFs files you provided me"}
34
+ ]
35
+
36
+ @st.cache_resource(show_spinner=False) # Añade decorador de caché
37
+ def cargar_embedmodel_y_llmmodel():
38
+ return True
39
+
40
+ #esta variable es para tener aqui un listado de aquellos ficheros que se han ido subiendo
41
+ archivos = []
42
+
43
+ ## carga y almacenamiento de ficheros almacenada, acepta varios.
44
+ with st.sidebar:
45
+ archivos = load_name_files(FILE_LIST)
46
+ files_uploaded = st.file_uploader(
47
+ "Carga tus ficheros PDF",
48
+ type="pdf",
49
+ accept_multiple_files=True,
50
+ on_change=st.cache_resource.clear
51
+ )
52
+
53
+ if st.button("Guardar y procesar por LLM", type="secondary",help="donde buscará lo que comparará"):
54
+ for pdf in files_uploaded:
55
+ if pdf is not None and pdf.name not in archivos:
56
+ archivos.append(pdf.name)
57
+
58
+ archivos = save_name_files(FILE_LIST, archivos)
59
+
60
+
61
+ if len(archivos)>0:
62
+ st.write('Los archivos PDF se han cargados:')
63
+ lista_documentos = st.empty()
64
+ with lista_documentos.container():
65
+ for arch in archivos:
66
+ st.write(arch)
67
+ if st.button('Borrar ficheros'):
68
+ archivos = []
69
+ clean_files(FILE_LIST)
70
+ lista_documentos.empty()
71
+
72
+
73
+ # comprueba que hay archivos a ser tratados
74
+ if len(archivos)>0:
75
+ # comprueba que hay consulta a responder
76
+ if user_question := st.chat_input("Realizar consulta:"):
77
+ st.session_state.messages.append({"role": "user", "content": user_question})
78
+
79
+ if user_question:
80
+ for message in st.session_state.messages: # Muestra anteriores mensajes
81
+ with st.chat_message(message["role"]):
82
+ st.write(message["content"])
83
+
84
+ alert = st.warning("Sea paciente") # Mensaje de aviso o warning al usuario
85
+ time.sleep(3) # establece tiempo espera en 3 segundos
86
+ alert.empty() # borra el aviso
87
+
88
+ # se define el analizador-parser de los documentos.
89
+ os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
90
+ parser = LlamaParse(
91
+ ## api_key=os.environ["LLAMA_CLOUD_API_KEY"], ##API de acceso a Cloud de LlamaIndex
92
+ api_key=LLAMA_CLOUD_API_KEY,
93
+ result_type="markdown", # se toma "markdown", tambien hay text disponible
94
+ verbose=True,
95
+ )
96
+
97
+ cargar_embedmodel_y_llmmodel()
98
+
99
+ #se parametrizan los modelos de embedding y LLM
100
+ embed_model=OpenAIEmbedding(model="text-embedding-3-small") #embeddings para base de conocimiento
101
+ llm = OpenAI(model="gpt-3.5-turbo-0125") #modelo LLM usado
102
+
103
+ Settings.llm = llm
104
+ Settings.embed_model = embed_model
105
+
106
+
107
+ tratar = load_name_files(FILE_LIST) ##variable que tomará los ficheros a tratar recuperados de funcion
108
+ # st.write(tratar[0]) # se puede desasteriscar en desarrollo para apoyo
109
+ # st.write(tratar[1]) # se puede desasteriscar en desarrollo para apoyo
110
+
111
+
112
+ # Carga de los ficheros mediante LlamaParse, se ejecutará job para cada analizador-parser de los mismos
113
+ docs_202401 = parser.load_data( f'{tratar[0]}')
114
+ docs_202402 = parser.load_data( f'{tratar[1]}')
115
+
116
+ #uso de MarkdownElementNodeParser para analizar la salida de LlamaParse mediante un motor de consultas de recuperación(recursivo)
117
+ from llama_index.core.node_parser import MarkdownElementNodeParser
118
+ node_parser = MarkdownElementNodeParser(llm=OpenAI(model="gpt-3.5-turbo-0125"), num_workers=8)
119
+
120
+ import pickle
121
+ from llama_index.postprocessor.flag_embedding_reranker import FlagEmbeddingReranker
122
+ # se parametriza el modelo reranker
123
+ reranker = FlagEmbeddingReranker(
124
+ top_n=5,
125
+ model="BAAI/bge-reranker-large",
126
+ )
127
+ #funcion para Facilitar el motor de consultas sobre el almacén de vectores, y poderse realizar la recuperación.
128
+ def create_query_engine_over_doc(docs, nodes_save_path=None):
129
+ """Big function to go from document path -> recursive retriever."""
130
+ if nodes_save_path is not None and os.path.exists(nodes_save_path):
131
+ raw_nodes = pickle.load(open(nodes_save_path, "rb"))
132
+ else:
133
+ raw_nodes = node_parser.get_nodes_from_documents(docs)
134
+ if nodes_save_path is not None:
135
+ pickle.dump(raw_nodes, open(nodes_save_path, "wb"))
136
+
137
+ base_nodes, objects = node_parser.get_nodes_and_objects(
138
+ raw_nodes
139
+ )
140
+
141
+ ### Recuperador-retriever
142
+ # indice y motor
143
+ vector_index = VectorStoreIndex(nodes=base_nodes+objects)
144
+ query_engine = vector_index.as_query_engine(
145
+ similarity_top_k=15,
146
+ node_postprocessors=[reranker]
147
+ )
148
+ return query_engine, base_nodes, vector_index ###devuelve motor de consultas y nodos
149
+
150
+ ## motores de consulta y nodos para cada documento usando la función anterior.
151
+ ## En los ficheros .pkl se puede ver la estructura de los documentos que ha conformado o analizado y será con la que trabajará.
152
+ query_engine_202401, nodes_202401,vindex1 = create_query_engine_over_doc(
153
+ docs_202401, nodes_save_path="202401_nodes.pkl"
154
+ )
155
+ query_engine_202402, nodes_202402,vindex2 = create_query_engine_over_doc(
156
+ docs_202402, nodes_save_path="202402_nodes.pkl"
157
+ )
158
+
159
+ from llama_index.core.tools import QueryEngineTool, ToolMetadata
160
+ from llama_index.core.query_engine import SubQuestionQueryEngine
161
+
162
+ from llama_index.core.llms import ChatMessage
163
+
164
+ # motor de consulta como tool, configuración y contexto de los datos que deberá proveer por los que será consultado
165
+ # debajo se usa como motor de subconsultas SubQuestionQueryEngine
166
+ query_engine_tools = [
167
+ QueryEngineTool(
168
+ query_engine=query_engine_202401,
169
+ metadata=ToolMetadata(
170
+ name="pdf_ENERO",
171
+ description=(
172
+ # "Provides information about Datos del Producto for ENERO"
173
+ # "Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases, Usos y Dosis Autorizados,Plazos de Seguridad"
174
+ """\
175
+ The documents provided are plant protection product data sheets in PDF format.
176
+ Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases,
177
+ Usos y Dosis Autorizados,Plazos de Seguridad:
178
+ # Datos del Producto
179
+ |Numero de Registro|
180
+ |Estado|
181
+ |Fechas Inscripción|
182
+ |Renovación|
183
+ |Caducidad|
184
+ |Nombre Comercial|
185
+
186
+ # Titular
187
+
188
+ # Fabricante
189
+
190
+ # Composición
191
+
192
+ # Envases
193
+
194
+ # Usos y Dosis Autorizados
195
+ |USO|
196
+ |AGENTE|
197
+ |Dosis|
198
+ |Condic. Especifico|
199
+
200
+ """
201
+ ),
202
+ ),
203
+ ),
204
+ QueryEngineTool(
205
+ query_engine=query_engine_202402,
206
+ metadata=ToolMetadata(
207
+ name="pdf_FEBRERO",
208
+ description=(
209
+ # "Provides information about Datos del Producto for FEBRERO"
210
+ # "Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases, Usos y Dosis Autorizados,Plazos de Seguridad"
211
+ """\
212
+ The documents provided are plant protection product data sheets in PDF format.
213
+ Provides information about values of fields of Datos del Producto, Titular, Fabricante,Composicion,Envases,
214
+ Usos y Dosis Autorizados,Plazos de Seguridad:
215
+ # Datos del Producto
216
+ |Numero de Registro|
217
+ |Estado|
218
+ |Fechas Inscripción|
219
+ |Renovación|
220
+ |Caducidad|
221
+ |Nombre Comercial|
222
+
223
+ # Titular
224
+
225
+ # Fabricante
226
+
227
+ # Composición
228
+
229
+ # Envases
230
+
231
+ # Usos y Dosis Autorizados
232
+ |USO|
233
+ |AGENTE|
234
+ |Dosis|
235
+ |Condic. Especifico|
236
+
237
+ """
238
+ ),
239
+ ),
240
+ ),
241
+ ]
242
+ # subconsultas con tool creada a través de SubQuestionQueryEngine
243
+ sub_query_engine = SubQuestionQueryEngine.from_defaults(
244
+ query_engine_tools=query_engine_tools,
245
+ llm=llm
246
+ )
247
+
248
+ if "chat_engine" not in st.session_state.keys(): # Initializa motor chat
249
+ # para que generen las subconsultas con la consulta-query del usuario
250
+ streaming_response = sub_query_engine.query(user_question)
251
+
252
+ ## If last message is not from assistant, generate a new response
253
+ if st.session_state.messages[-1]["role"] != "assistant":
254
+ with st.chat_message("assistant"):
255
+ with st.spinner("Thinking..."): #figura del spinner de streamlit mientras se ejecuta bloque
256
+ response = st.write(streaming_response.response) #respuesta entregada a la query-consulta del usuario
257
+ st.session_state.messages.append({"role": "assistant", "content": response})
258
+