Skip to content

Commit

Permalink
Added MultiPage support on UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Josemvg committed Feb 5, 2022
1 parent fbc35d9 commit 710d496
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 158 deletions.
40 changes: 40 additions & 0 deletions ui/multipage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import streamlit as st

# Define the multipage class to manage the multiple apps in our program
class MultiPage:
"""
Clase que gestiona multiples paginas en una misma aplicacion de streamlit.
"""
def __init__(self) -> None:
"""
Constructor de la clase MultiPage
"""
#Atributo pages, lista de diccionarios con las subpaginas de nuestra interfaz
self.pages = []

def add_page(self, title, func) -> None:
"""
Metodo que agrega una pagina a nuestro proyecto. Argumentos:
- title: Titulo de la pagina, sera el que aparezca en el selector
- func: Funcion de Python que ejecutara nuestra interfaz para correr la pagina en cuestion
"""
self.pages.append(
{
"title": title,
"function": func
}
)

def run(self):
"""
Funcion que ejecuta el codigo de la aplicacion
"""
#Selector
page = st.sidebar.selectbox(
'App Navigation',
self.pages,
format_func=lambda page: page['title']
)

# run the app function
page['function']()
13 changes: 13 additions & 0 deletions ui/pages/dataset_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import streamlit as st

def app():

#Subtitulo de la seccion de subida de conjuntos de datos
st.subheader('Dataset Upload')

#Texto del cuerpo de la pagina web
st.markdown("""
You may upload your dataset below. For it to correctly be processed and uploaded to our dataset database, please follow these guidelines:
""", unsafe_allow_html=True)

inputBuffer = st.file_uploader("Upload an Image", type=["csv","json"])
150 changes: 150 additions & 0 deletions ui/pages/question_answering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import streamlit as st
import requests
from annotated_text import annotated_text
import operator
from utils import db
import random

def queryJSON(queryURL, question):
"""
Funcion auxiliar que realiza las preguntas al servidor de EQA
"""
files = {
'question': (None, question),
}
response = requests.get(queryURL, files = files)
return response.json()

def app():

@st.cache(show_spinner=False, allow_output_mutation=True)
def getAnswers(data):
"""
Funcion auxiliar que obtiene una lista con todas las respuestas sobre las distintas bases de conocimiento
"""
answerList = [

]

for i in knowledgeBases:
queryURL = "http://127.0.0.1:5000/muheqa/" + i + "/en?evidence=true"
answer = queryJSON(queryURL,data["question"])
answer["source"] = i
answerList.append(answer)

return answerList

def annotateContext(response, answer, context):
'''
Funcion auxiliar que anota la respuesta sobre el texto de evidencia
'''
tag = "ANSWER"
color = "#adff2f"
if response['result'] != response['answer']:
answer = response['result']
tag = "EVIDENCE"
color = "#8ef"

answerPosition = context.find(answer)
answerPositionEnd = answerPosition + len(answer)
annotated_text(context[:answerPosition],(answer,tag,color),context[answerPositionEnd:],)

#Creamos la conexion para la base de datos de validacion
worksheet = db.connectToSheet()

#Subtitulo de la seccion de pregunta y respuesta
st.subheader('MuHeQa UI - Question Answering over Multiple and Heterogeneous Knowledge Bases')

#Texto del cuerpo de la pagina web con Markdown (convierte de texto a HTML)
st.markdown("""
Write any question below or use a random one from a pre-loaded datasets!
""", unsafe_allow_html=True)

#Lista de Hojas de Calculo con Datasets en nuestro Libro
datasetList = db.getDatasetsInSheet(worksheet)

#Obtenemos el contenido de cada una de estas hojas
recordList = []
#Creamos una lista de listas para dicho contenido, donde cada lista sera un dataset (hoja)
for i in datasetList:
recordList.append(db.getRecordsInSheet(i))

#Buscador para realizar preguntas
question = st.text_input("")

#Creamos la lista para el selector
selectorList = ["All"]
#Quitamos "_Validation" del nombre de las hojas del Libro de Calculo
selectorList.extend([i.split("_")[0] for i in datasetList])

#Selector para el Dataset del que provendran las preguntas aleatorias
dataset = st.selectbox("Select a DataSet", selectorList)
#Boton que hace una pregunta aleatoria
randomQuestion = st.button("Random Question")

if randomQuestion:
randomDict = random.choice(random.choices(recordList, weights=map(len, recordList))[0])
print(randomDict)
question = randomDict["question"]
modelAnswer = randomDict["answer"]

data = {
'question': question,
'answerNumber': 10
}

#Establecemos el titulo de la barra lateral
st.sidebar.subheader('Options')
#Control deslizante para el numero de respuestas a mostrar
answerNumber = st.sidebar.slider('How many relevant answers do you want?', 1, 10, 5)

#Lista de bases de conocimiento sobre las que haremos nuestra consulta
knowledgeBases = ["wikidata","dbpedia","cord19"]

if question:
st.write("**Question: **", question)
if modelAnswer:
#Mostramos la respuesta modelo
st.write("**Expected Answer: **", modelAnswer)
st.write("\n")
#Reseteamos el valor de la respuesta modelo
modelAnswer = None
#Mensaje de carga para las preguntas. Se muestra mientras que estas se obtienen.
with st.spinner(text=':hourglass: Looking for answers...'):
counter = 0
buttonKey = 1
results = getAnswers(data)
results.sort(key = operator.itemgetter('confidence'), reverse = True)
for i in results:
if counter >= answerNumber:
break
counter += 1
answer = i['answer']
if answer:
st.write("**Answer: **", answer)
context = '...' + i['evidence'] + '...'
source = i['source']
relevance = i['confidence']
annotateContext(i, answer, context)
'**Relevance:** ', relevance , '**Source:** ' , source
col1, col2 = st.columns([1,1])
with col1:
isRight = st.button("👍", buttonKey)
with col2:
isWrong = st.button("👎", buttonKey + 1)
buttonKey += 2
#Si se pulsa el boton de correcto/incorrecto:
if isRight or isWrong:
#Mensaje de que el input del usuario ha sido registrado
st.success("✨ Thanks for your input!")
#Insertamos en la Spreadsheet de Google
#db.insert(conn, [[question,source,answer,isRight]])
#Reseteamos los valores de los botones
isRight = False
isWrong = False


#Checkbox. Si tenemos respuesta y la caja es marcada, imprimimos las respuestas JSON obtenidas.
if question and st.sidebar.checkbox('Show JSON Response', key = 0):
st.subheader('API JSON Response')
st.write(results)
6 changes: 3 additions & 3 deletions ui/run_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ def runServer(dir):
"""
Funcion auxiliar que ejecuta el servidor de EQA
"""
p = subprocess.Popen(["python", "manage.py", "runserver"], cwd = dir)
subprocess.Popen(["python", "manage.py", "runserver"], cwd = dir)

def checkEQAServer():
"""
"""
Funcion auxiliar que comprueba que el servidor de EQA esta corriendo
haciendo una pregunta al servidor y viendo que no de ConnectionError
TO-DO: Usar HEAD Request para ahorrar recursos
Expand Down Expand Up @@ -42,4 +42,4 @@ def checkEQAServer():
checkEQAServer()

#Corremos la interfaz web
p = subprocess.run(["streamlit", "run", "webapp.py"], cwd = fileDir)
subprocess.run(["streamlit", "run", "webapp.py"], cwd = fileDir)
Loading

0 comments on commit 710d496

Please sign in to comment.