|
|
import streamlit as st |
|
|
from qstn.prompt_builder import LLMPrompt, generate_likert_options |
|
|
from qstn.utilities.prompt_templates import ( |
|
|
LIST_OPTIONS_DEFAULT, |
|
|
SCALE_OPTIONS_DEFAULT, |
|
|
) |
|
|
|
|
|
from gui_elements.stateful_widget import StatefulWidgets |
|
|
|
|
|
st.set_page_config(layout="wide") |
|
|
st.title("Likert Scale Options Generator") |
|
|
st.write( |
|
|
"This interface allows you to configure and generate Likert scale answer options by adjusting the parameters below." |
|
|
) |
|
|
st.divider() |
|
|
|
|
|
if "questionnaires" not in st.session_state: |
|
|
st.error("You need to first upload a questionnaire and the population you want to survey.") |
|
|
st.stop() |
|
|
disabled = True |
|
|
else: |
|
|
disabled = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state = StatefulWidgets() |
|
|
|
|
|
|
|
|
with st.container(border=True): |
|
|
|
|
|
st.subheader("Main Configuration") |
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
|
|
with col1: |
|
|
n_options = state.create( |
|
|
st.number_input, |
|
|
"n_options", |
|
|
"Number of Options (n)", |
|
|
initial_value=5, |
|
|
min_value=2, |
|
|
step=1, |
|
|
help="The total number of choices in the scale.", |
|
|
) |
|
|
|
|
|
with col2: |
|
|
idx_type = state.create( |
|
|
st.selectbox, |
|
|
"idx_type", |
|
|
"Index Type", |
|
|
initial_value="integer", |
|
|
options=["integer", "char_low", "char_up"], |
|
|
help="The type of index to use for the options.", |
|
|
) |
|
|
|
|
|
with col3: |
|
|
start_idx = state.create( |
|
|
st.number_input, |
|
|
"start_idx", |
|
|
"Starting Index", |
|
|
initial_value=1, |
|
|
step=1, |
|
|
help="The number to start counting from (e.g., 1).", |
|
|
) |
|
|
|
|
|
|
|
|
st.subheader("Ordering and Structure") |
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
|
|
with col1: |
|
|
only_from_to_scale = state.create( |
|
|
st.checkbox, |
|
|
"only_from_to_scale", |
|
|
"From-To Scale Only", |
|
|
initial_value=False, |
|
|
help="If checked, only the first and last answer labels are display e.g. 1 Strongly Disagree to 5 Strongly agree.", |
|
|
) |
|
|
|
|
|
with col2: |
|
|
random_order = state.create( |
|
|
st.checkbox, |
|
|
"random_order", |
|
|
"Random Order", |
|
|
initial_value=False, |
|
|
help="Randomize the order of options.", |
|
|
) |
|
|
|
|
|
with col3: |
|
|
reversed_order = state.create( |
|
|
st.checkbox, |
|
|
"reversed_order", |
|
|
"Reversed Order", |
|
|
initial_value=False, |
|
|
help="Reverse the order of options.", |
|
|
) |
|
|
|
|
|
with col4: |
|
|
even_order = state.create( |
|
|
st.checkbox, |
|
|
"even_order", |
|
|
"Even Order", |
|
|
initial_value=False, |
|
|
help="If there is an uneven number of answer texts, the middle section is automatically removed.", |
|
|
) |
|
|
|
|
|
|
|
|
st.subheader("Answer Texts") |
|
|
|
|
|
answer_texts = state.create( |
|
|
st.text_area, |
|
|
"answer_texts", |
|
|
"Enter Answer Texts (one per line)", |
|
|
initial_value="Strongly Disagree\nDisagree\nNeutral\nAgree\nStrongly Agree", |
|
|
height=150, |
|
|
help="Enter the labels for each answer option.", |
|
|
) |
|
|
|
|
|
|
|
|
with st.expander("Advanced Configuration"): |
|
|
options_separator = state.create( |
|
|
st.text_input, |
|
|
"options_separator", |
|
|
"Options Separator", |
|
|
initial_value=", ", |
|
|
help="The character(s) used to separate options in the final string.", |
|
|
) |
|
|
list_prompt_template = state.create( |
|
|
st.text_area, |
|
|
"list_prompt_template", |
|
|
"List Prompt Template", |
|
|
initial_value=LIST_OPTIONS_DEFAULT, |
|
|
height=100, |
|
|
help="Write how the options should be presented to the model.", |
|
|
) |
|
|
scale_prompt_template = state.create( |
|
|
st.text_area, |
|
|
"scale_prompt_template", |
|
|
"Scale Prompt Template", |
|
|
initial_value=SCALE_OPTIONS_DEFAULT, |
|
|
height=100, |
|
|
help="Write how the options should be presented to the model.", |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
submitted = st.button("Confirm and Generate Options", disabled=disabled, type="primary", use_container_width=True) |
|
|
|
|
|
if st.button("Skip", use_container_width=True, icon="❌"): |
|
|
st.session_state.survey_options = None |
|
|
st.switch_page("pages/02_Prompt_Configuration.py") |
|
|
|
|
|
|
|
|
if submitted: |
|
|
|
|
|
|
|
|
|
|
|
answer_texts_list = [ |
|
|
text.strip() for text in answer_texts.split("\n") if text.strip() |
|
|
] |
|
|
|
|
|
|
|
|
validation_ok = True |
|
|
if only_from_to_scale and len(answer_texts_list) != 2: |
|
|
st.error( |
|
|
f"Error: When 'From-To Scale Only' is selected, you must provide exactly 2 answer texts. You provided {len(answer_texts_list)}." |
|
|
) |
|
|
validation_ok = False |
|
|
|
|
|
if not only_from_to_scale and len(answer_texts_list) != n_options: |
|
|
st.error( |
|
|
f"Error: The number of answer texts ({len(answer_texts_list)}) must match the 'Number of Options' ({n_options})." |
|
|
) |
|
|
validation_ok = False |
|
|
|
|
|
if reversed_order and random_order: |
|
|
st.error(f"Error: Reversed Order and Random Order cannot both be true.") |
|
|
validation_ok = False |
|
|
|
|
|
if validation_ok: |
|
|
survey_options = generate_likert_options( |
|
|
n=n_options, |
|
|
answer_texts=answer_texts_list, |
|
|
only_from_to_scale=only_from_to_scale, |
|
|
random_order=random_order, |
|
|
reversed_order=reversed_order, |
|
|
even_order=even_order, |
|
|
start_idx=start_idx, |
|
|
list_prompt_template=list_prompt_template, |
|
|
scale_prompt_template=scale_prompt_template, |
|
|
options_separator=options_separator, |
|
|
idx_type=idx_type, |
|
|
) |
|
|
|
|
|
st.session_state.survey_options = survey_options |
|
|
st.switch_page("pages/02_Prompt_Configuration.py") |
|
|
|
|
|
|
|
|
|