Spaces:
Runtime error
Runtime error
jorge-henao
commited on
Commit
·
c71de7a
1
Parent(s):
e2305e9
space copied from https://huggingface.co/spaces/jorge-henao/ask2democracycol
Browse files- README.md +6 -6
- about.py +53 -0
- app.py +158 -0
- config.py +12 -0
- pinecone_document_store.db +0 -0
- pinecone_quieries.py +170 -0
- requirements.txt +4 -0
- samples.py +37 -0
README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
---
|
2 |
-
title: Ask2democracy
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: streamlit
|
7 |
-
sdk_version: 1.
|
8 |
app_file: app.py
|
9 |
-
pinned:
|
10 |
license: apache-2.0
|
11 |
---
|
12 |
|
|
|
1 |
---
|
2 |
+
title: Ask2democracy - IA para las discusiones democráticas
|
3 |
+
emoji: 🧐 📄 🇨🇴
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: blue
|
6 |
sdk: streamlit
|
7 |
+
sdk_version: 1.10.0
|
8 |
app_file: app.py
|
9 |
+
pinned: True
|
10 |
license: apache-2.0
|
11 |
---
|
12 |
|
about.py
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pinecone_quieries import PineconeProposalQueries
|
2 |
+
import streamlit as st
|
3 |
+
|
4 |
+
def show_about_ask2democracy():
|
5 |
+
description = """
|
6 |
+
<h2>Sobre esta iniciativa</h2>
|
7 |
+
<p>El debate ciudadano generalmente está sustentado en documentos que salvo pocas excepciones, casi nadie lee.
|
8 |
+
En este demo se han indexado algunos textos relevantes para la discución pública que suelen estar dispersos y poco accesibles. Además, se apoya en el estado del arte de la inteligencia artificial (abajo más detalles) , permitiendo explorar los documentos haciéndoles preguntas en español.
|
9 |
+
<p>
|
10 |
+
También se busca contribuir a la inteligencia artificial abierta y en español, mediante la construcción de un dataset y el entrenamiento de un modelo de lenguaje adaptado para las discusiones ciudadanas. Algo que puede ayudar a elevar la calidad del debate en todos los países de habla hispana.
|
11 |
+
<p>
|
12 |
+
Textos indexados: Propuesta reforma pensional de Marzo 22 de 2023, Propuesta reforma de la salud del 13 febrero 2023 , Capítulo de hallazgos y recomendaciones de la comisión de la verdad (trabajo en progreso, si quieres apoyar escríbeme)
|
13 |
+
<div align="right">
|
14 |
+
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'>LinkedIn</a> <a href="https://linktr.ee/jorgehenao" target='_blank'>Linktree</a>
|
15 |
+
</div>
|
16 |
+
<p>
|
17 |
+
<h2>¿Cómo utilizar este espacio?</h2>
|
18 |
+
Selecciona el de documento que quieres explorar en el panel de la izquierda, escribe preguntas en la caja de texto y presiona el botón.
|
19 |
+
No se trata de un sistema de búsquedas basado en palabras clave, por el contrario, puedes redactar preguntas más extensas y elaboradas. Cuanto más contexto le des a la pregunta mejores resultados obtienes.
|
20 |
+
<h2>Integración opcional con OpenAI</h2>
|
21 |
+
Este demo usa recursos de computo limitados sin costo para la gente (si quieres ayudar a que sea más rápido ecríbeme).
|
22 |
+
De manera opcional, si tienes una cuenta en OpenAI también puedes activar la integración copiando tu API key en el panel de la izquierda.
|
23 |
+
Una vez ingreses el api key, cada vez que hagas una pregunta el sistema la usará para elaborar una respuesta breve a partir de los resultados de búsqueda obtenidos, basándose siempre en las fuentes oficiales.
|
24 |
+
También puedes configurar que tan larga quieres que sea la respuesta (max tokens), y que tan creativas (temperatura).
|
25 |
+
<p><p><b>Nota:El sistema no guarda tu API key, sólo la utiliza para aumentar tus consultas mientras lo uses.</b>
|
26 |
+
<h2>Inteligencia artificial y democracia</h2>
|
27 |
+
Pretende ayudar a construir democracia participativa apaloncándose en el estado del arte de la inteligencia artificial.
|
28 |
+
Al ser un demo accesible en web, puede ayudarle a un ciudadano del común a tener una opinión más informada, ayudándole a ser partícipe del debate público haciendo preguntas directamente a las fuentes en su propio lenguaje y llegando a sus propias conclusiones.
|
29 |
+
<p><p>
|
30 |
+
Respecto a la inteligencia artificial hay algunas hipótesis que se quieren probar:
|
31 |
+
<ul>
|
32 |
+
<li> ¿Que tan efectivo puede ser un sistema de búsquedas con modelos de inteligencia artificial abiertos, para ayudar a la gente a entender discuciones ciudadanas relevantes en español? </li>
|
33 |
+
<li> ¿Que tan creativa puede ser la ingeligencia artificial en esa materia?</li>
|
34 |
+
<li> ¿Puede la inteligencia artificial abierta, ayudarle a la gente a entender documentos legislativos: propuestas de reforma, planes de gobierno, y en general documentos de discución pública?</li>
|
35 |
+
<li> ¿Puede la inteligencia artificial abierta igualar o mejorar sistemas como ChatGPT/GPT-4 de OpenAI para el entendimiento de discusiones ciudadanas en español?</li>
|
36 |
+
</ul>
|
37 |
+
Por lo anterior se prentende la construcción de un dataset. Dataset usado para entrenar(fine-tunning) uno o más modelos(Bert/GPT-2/Alpaca...) adapatado a discuciones ciudadanas en español.
|
38 |
+
Algo que puede ayudar a elevar el nivel del debate público en paises de habla hispana.
|
39 |
+
<h2>Ask2Democracy v0.3</h2>
|
40 |
+
Esta version usa sentence transformers (Cosine similarity), una base de dactos vectorial Pinecone para almacenar los embeddings, Haystack framework y la integración con OpenAI.
|
41 |
+
Los modelos de lenguaje transformers utilizados son:
|
42 |
+
<code>
|
43 |
+
sentence-transformers/multi-qa-MiniLM-L6-cos-v1
|
44 |
+
deepset/xlm-roberta-base-squad2-distilled
|
45 |
+
</code>
|
46 |
+
<a href= "https://github.com/jorge-henao/ask_to_democracy"> repo en github con FastAPI</a>
|
47 |
+
<h2>Beta disclaimer</h2>
|
48 |
+
Las respuestas que arroja el sistema no han sido pregrabadas ni basadas en opiniones. Todas son respuestas extraídas de fuentes oficiales.
|
49 |
+
Este demo usa modelos de lenguaje para entender el lenguaje español, sin embargo, necesita de un mayor entrenamiento por lo que, en ocasiones, puede ser confuso y no tan preciso.
|
50 |
+
Si quieres apoyar escríbeme a <a href="mailto:jorge.henao@diezonce.co">jorge.henao@diezonce.co</a>
|
51 |
+
</p>
|
52 |
+
"""
|
53 |
+
st.markdown(description, unsafe_allow_html=True)
|
app.py
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
from about import show_about_ask2democracy
|
3 |
+
import streamlit as st
|
4 |
+
from pinecone_quieries import PineconeProposalQueries
|
5 |
+
from config import Config
|
6 |
+
from samples import *
|
7 |
+
|
8 |
+
queries = PineconeProposalQueries (index_name= Config.index_name,
|
9 |
+
api_key = Config.es_password,
|
10 |
+
environment = Config.pinecone_environment,
|
11 |
+
embedding_dim = Config.embedding_dim,
|
12 |
+
reader_name_or_path = Config.reader_model_name_or_path,
|
13 |
+
use_gpu = Config.use_gpu,
|
14 |
+
OPENAI_key= None)
|
15 |
+
|
16 |
+
def search(question, retriever_top_k, reader_top_k, selected_index=None):
|
17 |
+
filters = {"source_title": selected_index}
|
18 |
+
query_result = queries.search_by_query(query = question,
|
19 |
+
retriever_top_k = retriever_top_k,
|
20 |
+
reader_top_k = reader_top_k,
|
21 |
+
filters = filters)
|
22 |
+
result = []
|
23 |
+
for i in range(0, len(query_result)):
|
24 |
+
item = query_result[i]
|
25 |
+
result.append([[i+1], item.answer.replace("\n",""), item.context[:250],
|
26 |
+
item.meta['title'], item.meta['source_title'],
|
27 |
+
int(item.meta['page']), item.meta['source_url']])
|
28 |
+
return result
|
29 |
+
|
30 |
+
def search_and_show_results(query:str, retriever_top_k = 5, reader_top_k =3, selected_index=None):
|
31 |
+
stt = time.time()
|
32 |
+
results = search(query, retriever_top_k=retriever_top_k,
|
33 |
+
reader_top_k=reader_top_k, selected_index=selected_index)
|
34 |
+
ent = time.time()
|
35 |
+
elapsed_time = round(ent - stt, 2)
|
36 |
+
|
37 |
+
st.write(f"**Resultados encontrados para la pregunta** \"{query}\" ({elapsed_time} sec.):")
|
38 |
+
for i, answer in enumerate(results):
|
39 |
+
st.subheader(f"{answer[1]}")
|
40 |
+
doc = answer[2][:250] + "..."
|
41 |
+
st.markdown(f"{doc}[Lee más aquí]({answer[6]})", unsafe_allow_html=True)
|
42 |
+
st.caption(f"Fuente: {answer[4]} - Artículo: {answer[3]} - Página: {answer[5]}")
|
43 |
+
|
44 |
+
def search_and_generate_answer(question, retriever_top_k, generator_top_k,
|
45 |
+
openai_api_key, openai_model_name= "text-davinci-003",
|
46 |
+
temperature = .5, max_tokens = 30, selected_index = None):
|
47 |
+
filters = {"source_title": selected_index}
|
48 |
+
|
49 |
+
query_result = queries.genenerate_answer_OpenAI(query = question,
|
50 |
+
retriever_top_k = retriever_top_k,
|
51 |
+
generator_top_k = generator_top_k,
|
52 |
+
filters = filters, OPENAI_key = openai_api_key,
|
53 |
+
openai_model_name= openai_model_name,temperature = temperature, max_tokens = max_tokens)
|
54 |
+
result = []
|
55 |
+
for i in range(0, len(query_result)):
|
56 |
+
item = query_result[i]
|
57 |
+
source_title = item.meta['doc_metas'][0]['source_title']
|
58 |
+
source_url = item.meta['doc_metas'][0]['source_url']
|
59 |
+
chapter_titles = [source['title'] for source in item.meta['doc_metas']]
|
60 |
+
result.append([[i+1], item.answer.replace("\n",""),
|
61 |
+
source_title, source_url, str(chapter_titles)])
|
62 |
+
return result
|
63 |
+
|
64 |
+
def search_and_show_generative_results(query:str, retriever_top_k = 5, generator_top_k =1 , openai_api_key = None, openai_model_name = "text-davinci-003", temperature = .5, max_tokens = 30, selected_index = None):
|
65 |
+
# set start time
|
66 |
+
stt = time.time()
|
67 |
+
results = search_and_generate_answer(query, retriever_top_k = retriever_top_k,
|
68 |
+
generator_top_k= generator_top_k,
|
69 |
+
openai_api_key = openai_api_key,
|
70 |
+
openai_model_name= openai_model_name,
|
71 |
+
temperature = temperature, max_tokens = max_tokens,
|
72 |
+
selected_index = selected_index)
|
73 |
+
ent = time.time()
|
74 |
+
elapsed_time = round(ent - stt, 2)
|
75 |
+
st.write(f"**Respuesta generada para la pregunta** \"{query}\" ({elapsed_time} sec.):")
|
76 |
+
if results != None:
|
77 |
+
for i, answer in enumerate(results):
|
78 |
+
# answer starts with header
|
79 |
+
st.subheader(f"{answer[1]}")
|
80 |
+
st.caption(f"Fuentes: {answer[2]} - {answer[4]}")
|
81 |
+
st.markdown(f"[Lee más aquí]({answer[3]})")
|
82 |
+
|
83 |
+
|
84 |
+
indexes = [{"title": "Propuesta reforma a la salud 13 de febrero de 2023", "name": "Reforma de la salud 13 Febrero 2023", "samples": samples_reforma_salud},
|
85 |
+
{"title": "Propuesta reforma pensional marzo 22 de 2023", "name": "Reforma pensional Marzo 2023", "samples": samples_reforma_pensional},
|
86 |
+
{"title": "Hallazgos de la comisión de la verdad", "name": "Hallazgos y recomendaciones - 28 de Junio 2022", "samples": samples_hallazgos_paz}
|
87 |
+
]
|
88 |
+
|
89 |
+
|
90 |
+
|
91 |
+
index_titles = [item["title"] for item in indexes]
|
92 |
+
|
93 |
+
def get_selected_index_by_title(title):
|
94 |
+
for item in indexes:
|
95 |
+
if item["title"] == title:
|
96 |
+
return item["name"]
|
97 |
+
return None
|
98 |
+
|
99 |
+
def get_samples_for_index(title):
|
100 |
+
for item in indexes:
|
101 |
+
if item["title"] == title:
|
102 |
+
return item["samples"]
|
103 |
+
return None
|
104 |
+
|
105 |
+
def main():
|
106 |
+
st.title("Ask2Democracy 🇨🇴")
|
107 |
+
st.markdown("""
|
108 |
+
<div align="right">
|
109 |
+
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'>LinkedIn</a> <a href="https://linktr.ee/jorgehenao" target='_blank'>Linktree</a>
|
110 |
+
</div>""", unsafe_allow_html=True)
|
111 |
+
|
112 |
+
# session_state = st.session_state
|
113 |
+
# if "api_key" not in session_state:
|
114 |
+
# session_state.api_key = ""
|
115 |
+
|
116 |
+
with st.form("my_form"):
|
117 |
+
st.sidebar.title("Configuración de búsqueda")
|
118 |
+
with st.sidebar.expander("Parámetros de recuperación", expanded= True):
|
119 |
+
index = st.selectbox("Selecciona el documento que deseas explorar", index_titles)
|
120 |
+
top_k_retriever = st.slider("Retriever Top K", 1, 10, 5)
|
121 |
+
top_k_reader = st.slider("Reader Top K", 1, 10, 3)
|
122 |
+
|
123 |
+
with st.sidebar.expander("Configuración OpenAI"):
|
124 |
+
openai_api_key = st.text_input("API Key", type="password", placeholder="Copia aquí tu OpenAI API key (no será guardada)",
|
125 |
+
help="puedes obtener tu api key de OpenAI en https://platform.openai.com/account/api-keys.")
|
126 |
+
openai_api_model = st.text_input("Modelo", value= "text-davinci-003")
|
127 |
+
openai_api_temp = st.slider("Temperatura", 0.1, 1.0, 0.5, step=0.1)
|
128 |
+
openai_api_max_tokens = st.slider("Max tokens", 10, 100, 60, step=10)
|
129 |
+
|
130 |
+
# if openai_api_key:
|
131 |
+
# session_state.password = openai_api_key
|
132 |
+
|
133 |
+
sample_questions = get_samples_for_index(index).splitlines()
|
134 |
+
query = st.text_area("",placeholder="Escribe aquí tu pregunta, cuanto más contexto le des, mejor serán las respuestas")
|
135 |
+
with st.expander("Algunas preguntas de ejemplo", expanded= False):
|
136 |
+
for sample in sample_questions:
|
137 |
+
st.markdown(f"- {sample}")
|
138 |
+
|
139 |
+
submited = st.form_submit_button("Buscar")
|
140 |
+
if submited:
|
141 |
+
selected_index = get_selected_index_by_title(index)
|
142 |
+
if openai_api_key:
|
143 |
+
with st.expander("", expanded= True):
|
144 |
+
search_and_show_generative_results(query = query,retriever_top_k= top_k_retriever,
|
145 |
+
generator_top_k= 1, openai_api_key = openai_api_key,
|
146 |
+
openai_model_name = openai_api_model,
|
147 |
+
temperature= openai_api_temp,
|
148 |
+
max_tokens= openai_api_max_tokens,
|
149 |
+
selected_index = selected_index)
|
150 |
+
with st.expander("", expanded= True):
|
151 |
+
search_and_show_results(query, retriever_top_k=top_k_retriever,
|
152 |
+
reader_top_k=top_k_reader,
|
153 |
+
selected_index=selected_index)
|
154 |
+
else:
|
155 |
+
show_about_ask2democracy()
|
156 |
+
|
157 |
+
if __name__ == "__main__":
|
158 |
+
main()
|
config.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class Config():
|
2 |
+
es_host = "saimon-askwdemocracy.es.us-central1.gcp.cloud.es.io"
|
3 |
+
es_user = "elastic"
|
4 |
+
#es_password = "53f2a7a9-ea9d-4fd2-a8bc-f471b67f0262"
|
5 |
+
es_password = "1f45bf76-b600-42b3-b2cc-ab6062693eb7"
|
6 |
+
index_name = "docsreloaded"
|
7 |
+
reader_model_name_or_path = "deepset/xlm-roberta-base-squad2-distilled"
|
8 |
+
pinecone_environment="us-east-1-aws"
|
9 |
+
embedding_dim = 384
|
10 |
+
similarity="cosine"
|
11 |
+
#reader_model_name_or_path = "deepset/xlm-roberta-base-squad2"
|
12 |
+
use_gpu = True
|
pinecone_document_store.db
ADDED
Binary file (73.7 kB). View file
|
|
pinecone_quieries.py
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from abc import ABC, abstractmethod
|
3 |
+
from haystack.nodes import BM25Retriever, FARMReader
|
4 |
+
from haystack.document_stores import ElasticsearchDocumentStore
|
5 |
+
from haystack.pipelines import ExtractiveQAPipeline, DocumentSearchPipeline
|
6 |
+
from haystack.document_stores import PineconeDocumentStore
|
7 |
+
from haystack.nodes import EmbeddingRetriever, OpenAIAnswerGenerator
|
8 |
+
from json import JSONDecodeError
|
9 |
+
from pathlib import Path
|
10 |
+
from typing import List, Optional
|
11 |
+
|
12 |
+
import pandas as pd
|
13 |
+
|
14 |
+
from haystack import BaseComponent, Document
|
15 |
+
from haystack.document_stores import PineconeDocumentStore
|
16 |
+
from haystack.nodes import (
|
17 |
+
EmbeddingRetriever,
|
18 |
+
FARMReader
|
19 |
+
)
|
20 |
+
from haystack.pipelines import ExtractiveQAPipeline, Pipeline, GenerativeQAPipeline
|
21 |
+
from haystack.pipelines import BaseStandardPipeline
|
22 |
+
from haystack.nodes.reader import BaseReader
|
23 |
+
from haystack.nodes.retriever import BaseRetriever
|
24 |
+
from sentence_transformers import SentenceTransformer
|
25 |
+
|
26 |
+
import certifi
|
27 |
+
import datetime
|
28 |
+
import requests
|
29 |
+
from base64 import b64encode
|
30 |
+
|
31 |
+
ca_certs = certifi.where()
|
32 |
+
class QAPipeline(BaseStandardPipeline):
|
33 |
+
"""
|
34 |
+
Pipeline for Extractive Question Answering.
|
35 |
+
"""
|
36 |
+
|
37 |
+
def __init__(self, reader: BaseReader, retriever: BaseRetriever):
|
38 |
+
"""
|
39 |
+
:param reader: Reader instance
|
40 |
+
:param retriever: Retriever instance
|
41 |
+
"""
|
42 |
+
self.pipeline = Pipeline()
|
43 |
+
self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"])
|
44 |
+
self.pipeline.add_node(component=reader, name="Reader", inputs=["Retriever"])
|
45 |
+
self.metrics_filter = {"Retriever": ["recall_single_hit"]}
|
46 |
+
|
47 |
+
def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None):
|
48 |
+
"""
|
49 |
+
:param query: The search query string.
|
50 |
+
:param params: Params for the `retriever` and `reader`. For instance,
|
51 |
+
params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}}
|
52 |
+
:param debug: Whether the pipeline should instruct nodes to collect debug information
|
53 |
+
about their execution. By default these include the input parameters
|
54 |
+
they received and the output they generated.
|
55 |
+
All debug information can then be found in the dict returned
|
56 |
+
by this method under the key "_debug"
|
57 |
+
"""
|
58 |
+
|
59 |
+
output = self.pipeline.run(query=query, params=params, debug=debug)
|
60 |
+
return output
|
61 |
+
|
62 |
+
|
63 |
+
class DocumentQueries(ABC):
|
64 |
+
|
65 |
+
@abstractmethod
|
66 |
+
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, index_name: str = None, filters = None):
|
67 |
+
pass
|
68 |
+
|
69 |
+
class PineconeProposalQueries(DocumentQueries):
|
70 |
+
|
71 |
+
def __init__(self, index_name: str, api_key, reader_name_or_path: str, use_gpu = True,
|
72 |
+
embedding_dim = 384, environment = "us-east1-gcp", OPENAI_key = None) -> None:
|
73 |
+
|
74 |
+
reader = FARMReader(model_name_or_path = reader_name_or_path,
|
75 |
+
use_gpu = use_gpu, num_processes = 1,
|
76 |
+
context_window_size = 200)
|
77 |
+
|
78 |
+
self._initialize_pipeline(index_name, api_key, reader = reader, embedding_dim=
|
79 |
+
embedding_dim, environment = environment, OPENAI_key= OPENAI_key)
|
80 |
+
#self.log = Log(es_host= es_host, es_index="log", es_user = es_user, es_password= es_password)
|
81 |
+
self.OpenAI_api_key = None
|
82 |
+
|
83 |
+
def _initialize_pipeline(self, index_name, api_key, similarity = "cosine",
|
84 |
+
embedding_dim = 384, reader = None,
|
85 |
+
environment = "us-east1-gcp",
|
86 |
+
metadata_config = {"indexed": ["title", "source_title"]},
|
87 |
+
OPENAI_key = None):
|
88 |
+
if reader is not None:
|
89 |
+
self.reader = reader
|
90 |
+
|
91 |
+
#pinecone.init(api_key=es_password, environment="us-east1-gcp")
|
92 |
+
|
93 |
+
self.document_store = PineconeDocumentStore(
|
94 |
+
api_key = api_key,
|
95 |
+
environment = environment,
|
96 |
+
index = index_name,
|
97 |
+
similarity = similarity,
|
98 |
+
embedding_dim = embedding_dim,
|
99 |
+
metadata_config = {"indexed": ["title","source_title"]}
|
100 |
+
)
|
101 |
+
|
102 |
+
self.retriever = EmbeddingRetriever(
|
103 |
+
document_store= self.document_store,
|
104 |
+
embedding_model = "sentence-transformers/multi-qa-MiniLM-L6-cos-v1",
|
105 |
+
model_format="sentence_transformers"
|
106 |
+
)
|
107 |
+
|
108 |
+
self.extractive_pipe = ExtractiveQAPipeline (reader = self.reader,
|
109 |
+
retriever = self.retriever)
|
110 |
+
|
111 |
+
self.generative_OPENAI_pipe = None
|
112 |
+
if (OPENAI_key != None and OPENAI_key != ""):
|
113 |
+
OPENAI_generator = OpenAIAnswerGenerator(api_key = OPENAI_key,
|
114 |
+
model="text-davinci-003", temperature=.5, max_tokens=60)
|
115 |
+
self.generative_OPENAI_pipe = GenerativeQAPipeline(generator = OPENAI_generator,
|
116 |
+
retriever = self.retriever)
|
117 |
+
|
118 |
+
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, index_name: str = None, filters = None):
|
119 |
+
#self.document_store.update_embeddings(self.retriever, update_existing_embeddings=False)
|
120 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
121 |
+
"filters": filters},
|
122 |
+
"Reader": {"top_k": reader_top_k}}
|
123 |
+
prediction = self.extractive_pipe.run( query = query, params = params, debug = True)
|
124 |
+
return prediction["answers"]
|
125 |
+
|
126 |
+
def __initialize_openAIGEnerator(self, OPENAI_key, openai_model_name= "text-davinci-003", temperature = .5, max_tokens = 30):
|
127 |
+
if OPENAI_key != self.OpenAI_api_key:
|
128 |
+
OPENAI_generator = OpenAIAnswerGenerator(api_key=OPENAI_key,
|
129 |
+
model=openai_model_name, temperature= temperature, max_tokens=max_tokens)
|
130 |
+
self.generative_OPENAI_pipe = GenerativeQAPipeline(generator = OPENAI_generator,
|
131 |
+
retriever = self.retriever)
|
132 |
+
self.OpenAI_api_key = OPENAI_key
|
133 |
+
|
134 |
+
def genenerate_answer_OpenAI(self, query : str, retriever_top_k: int, generator_top_k: int, filters = None,
|
135 |
+
OPENAI_key = None, openai_model_name= "text-davinci-003",temperature = .5, max_tokens = 30):
|
136 |
+
if OPENAI_key != self.OpenAI_api_key:
|
137 |
+
self.__initialize_openAIGEnerator(OPENAI_key, openai_model_name, temperature, max_tokens)
|
138 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
139 |
+
"filters": filters},
|
140 |
+
"Generator": {"top_k": generator_top_k}}
|
141 |
+
prediction = self.generative_OPENAI_pipe.run( query = query, params = params)
|
142 |
+
return prediction["answers"]
|
143 |
+
else:
|
144 |
+
return None
|
145 |
+
|
146 |
+
def genenerate_answer_HF(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str = None, filters = None) :
|
147 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
148 |
+
"filters": filters},
|
149 |
+
"Generator": {"top_k": reader_top_k}}
|
150 |
+
prediction = self.generative_HF_pipe.run( query = query, params = params)
|
151 |
+
return prediction["answers"]
|
152 |
+
|
153 |
+
class Log():
|
154 |
+
|
155 |
+
def __init__(self, es_host: str, es_index: str, es_user, es_password) -> None:
|
156 |
+
self.elastic_endpoint = f"https://{es_host}:443/{es_index}/_doc"
|
157 |
+
self.credentials = b64encode(b"3pvrzh9tl:4yl4vk9ijr").decode("ascii")
|
158 |
+
self.auth_header = { 'Authorization' : 'Basic %s' % self.credentials }
|
159 |
+
|
160 |
+
def write_log(self, message: str, source: str) -> None:
|
161 |
+
created_date = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
|
162 |
+
post_data = {
|
163 |
+
"message" : message,
|
164 |
+
"createdDate": {
|
165 |
+
"date" : created_date
|
166 |
+
},
|
167 |
+
"source": source
|
168 |
+
}
|
169 |
+
r = requests.post(self.elastic_endpoint, json = post_data, headers = self.auth_header)
|
170 |
+
print(r.text)
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
sentence-transformers
|
2 |
+
farm-haystack[pinecone]
|
3 |
+
pinecone-client
|
4 |
+
streamlit==1.15.0
|
samples.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
samples_reforma_salud = """¿Que es el ADRES?
|
3 |
+
¿Cuándo se implementará el Sistema de Salud?
|
4 |
+
¿Cómo se implementará el Sistema de Salud?
|
5 |
+
¿Qué es principio de interpretación y fundamento de la transición en relación al Sistema de Salud?
|
6 |
+
¿Qué se garantiza la atención en todo momento con el nuevo Sistema de Salud?
|
7 |
+
¿Qué son los Centros de Atención Primaria Integrales y Resolutivos en Salud - CAPIRS?
|
8 |
+
¿Qué se garantiza durante el periodo de transición del nuevo Sistema de Salud?
|
9 |
+
¿Puede haber personas sin protección de su salud durante el periodo de transición?
|
10 |
+
¿Cuál es el derecho fundamental que se garantiza en todo momento durante la transición del nuevo Sistema de Salud?
|
11 |
+
¿Qué se debe realizar para garantizar la gestión de los recursos en el nivel nacional y desconcentrado?
|
12 |
+
¿Cómo se regirá el régimen de contratación de los contratos mencionados en el texto?
|
13 |
+
¿Qué son las cláusulas exorbitantes previstas en el estatuto General de Contratación de la administración pública?
|
14 |
+
¿Qué principios deben atender los contratos mencionados en el texto?
|
15 |
+
¿Cuál es el ámbito de aplicación de los contratos mencionados en el texto?
|
16 |
+
¿Quién tiene la responsabilidad de realizar la auditoría de las cuentas en relación a estos contratos?
|
17 |
+
¿Cuáles son las características que deben cumplir los contratos mencionados en el texto?
|
18 |
+
¿Qué se entiende por "coordinación" en el contexto de los contratos mencionados en el texto?
|
19 |
+
¿Qué objetivo se busca con los contratos mencionados en el texto?
|
20 |
+
¿Quién será el encargado de contratar los servicios de salud y otros requerimientos para el cumplimiento de su labor en el nivel regional?
|
21 |
+
¿Qué tipo de instituciones hospitalarias y ambulatorias se integran a la red de servicios del territorio?
|
22 |
+
¿Qué tarifas deben seguir las instituciones hospitalarias y ambulatorias para la prestación de servicios de salud?
|
23 |
+
¿Qué busca modular el régimen de tarifas y formas de pago para la prestación de servicios de salud?
|
24 |
+
¿Qué tipo de registro llevará el Fondo Regional de Salud?
|
25 |
+
¿Cuáles son algunas de las variables que se incluirán en el registro de cada servicio prestado y pagado?"""
|
26 |
+
|
27 |
+
samples_hallazgos_paz = """¿cantidad de víctimas en la masacre de bojayá?
|
28 |
+
¿periodo con más detenciones arbitrarias registradas?
|
29 |
+
¿cantidad de víctimas en la masacre de bojayá?
|
30 |
+
¿cuantas víctimas de desplazamiento en antioquia?"""
|
31 |
+
|
32 |
+
|
33 |
+
samples_reforma_pensional="""¿cuales son los pilares que se proponen?
|
34 |
+
¿cuanto será la cotización al pilar contributivo?
|
35 |
+
¿quienes serán los beneficiarios del pilar contributivo?
|
36 |
+
¿cual es el beneficio para las mujeres con hijos?
|
37 |
+
"""
|