Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,34 +13,43 @@ import io
|
|
| 13 |
import config
|
| 14 |
from openai import OpenAI
|
| 15 |
|
|
|
|
|
|
|
|
|
|
| 16 |
############################################################################################################
|
| 17 |
# Password protection
|
| 18 |
|
| 19 |
-
def
|
| 20 |
-
"""Returns `True` if the user had the correct password."""
|
| 21 |
-
|
| 22 |
-
def
|
| 23 |
-
"""Checks whether
|
| 24 |
-
if
|
| 25 |
-
st.session_state["
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
del st.session_state["password"] # Don't store the password.
|
| 27 |
else:
|
| 28 |
-
st.session_state["
|
| 29 |
|
| 30 |
-
# Return True if the
|
| 31 |
-
if st.session_state.get("
|
| 32 |
return True
|
| 33 |
|
| 34 |
-
# Show input for password.
|
| 35 |
-
st.text_input(
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
if "
|
| 39 |
-
|
| 40 |
return False
|
| 41 |
|
| 42 |
-
if not
|
| 43 |
-
st.stop() # Do not continue if
|
|
|
|
|
|
|
| 44 |
|
| 45 |
############################################################################################################
|
| 46 |
# Streamlit app layout
|
|
@@ -55,13 +64,6 @@ df = pd.read_csv(config.default_terms_csv)
|
|
| 55 |
st.title(config.app_title)
|
| 56 |
st.markdown(config.intro_para)
|
| 57 |
st.caption(config.app_author)
|
| 58 |
-
with st.expander("INSTRUCTIONS FOR STUDENTS:"):
|
| 59 |
-
st.markdown(config.instructions)
|
| 60 |
-
with st.expander("**INSTRUCTORS**: For a look at the current terms file driving the interaction, click here:"):
|
| 61 |
-
st.markdown("This is the terms.csv file that drives the interaction. You can edit this file to change the terms and context that the chatbot uses. You may add any term or phrase. You may leave the context blank if you prefer or you can add anything relevant that the GPT does not normally know about the term. This may include relevant learning objectives, course examples, notable scientists, assessment dates, syllabus information, etc.")
|
| 62 |
-
st.table(df)
|
| 63 |
-
with st.expander("**INSTRUCTORS**: For a look at the prompt driving the chatbot, click here:"):
|
| 64 |
-
st.markdown(config.display_prompt)
|
| 65 |
st.sidebar.title(config.sidebar_title)
|
| 66 |
with st.sidebar:
|
| 67 |
with st.expander("Click here for instructions."):
|
|
@@ -71,7 +73,6 @@ with st.sidebar:
|
|
| 71 |
# File Uploader in sidebar
|
| 72 |
|
| 73 |
# Load terms from a CSV file
|
| 74 |
-
# https://discuss.streamlit.io/t/how-to-upload-a-csv-file/7052/2
|
| 75 |
def load_terms(file_input):
|
| 76 |
try:
|
| 77 |
if isinstance(file_input, str):
|
|
@@ -133,52 +134,59 @@ st.sidebar.markdown('<hr>', unsafe_allow_html=True)
|
|
| 133 |
############################################################################################################
|
| 134 |
# Term Selection and session state
|
| 135 |
|
| 136 |
-
# Define a basic initial context at the beginning of your script
|
| 137 |
-
initial_context = {
|
| 138 |
-
"role": "system",
|
| 139 |
-
"content": config.initial_prompt
|
| 140 |
-
}
|
| 141 |
-
|
| 142 |
# Initialize the session state variables for selected term, context, and display messages
|
| 143 |
if 'selected_term' not in st.session_state:
|
| 144 |
st.session_state.selected_term = None
|
| 145 |
if 'selected_context' not in st.session_state:
|
| 146 |
st.session_state.selected_context = None
|
| 147 |
if 'display_messages' not in st.session_state:
|
| 148 |
-
st.session_state.display_messages = [
|
| 149 |
|
| 150 |
# Initialize session states for the selected term, counter, and display flag
|
| 151 |
-
if 'selected_term' not in st.session_state:
|
| 152 |
-
st.session_state.selected_term = None
|
| 153 |
if 'display_term' not in st.session_state:
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
# Dropdown menu for selecting a term
|
| 157 |
-
selected_term = st.selectbox('
|
|
|
|
| 158 |
if selected_term:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
selected_context = terms.loc[terms['TERM'] == selected_term, 'CONTEXT'].values[0]
|
| 160 |
st.session_state.selected_term = selected_term
|
| 161 |
st.session_state.selected_context = selected_context
|
| 162 |
st.session_state.display_term = True
|
| 163 |
-
|
| 164 |
-
# Ensure the session state variables are set correctly
|
| 165 |
-
# if st.session_state.get('selected_term') and st.session_state.get('selected_context'):
|
| 166 |
# Update the prompt for the API
|
| 167 |
updated_prompt = config.term_prompt(st.session_state.selected_term, st.session_state.selected_context, term_list)
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
# Reset the conversation with the new initial context
|
| 173 |
-
st.session_state.display_messages[0] = [initial_context]
|
| 174 |
|
| 175 |
# Display the selected term and its context
|
| 176 |
if st.session_state.display_term and st.session_state.selected_term:
|
| 177 |
st.header(st.session_state.selected_term)
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
|
| 183 |
############################################################################################################
|
| 184 |
# ChatGPT
|
|
@@ -190,20 +198,19 @@ if "openai_model" not in st.session_state:
|
|
| 190 |
st.session_state["openai_model"] = config.ai_model
|
| 191 |
|
| 192 |
if "display_messages" not in st.session_state:
|
| 193 |
-
st.session_state.display_messages
|
| 194 |
|
| 195 |
# Update initial_context with the latest selected term and context
|
| 196 |
if st.session_state.get('selected_term') and st.session_state.get('selected_context'):
|
| 197 |
updated_prompt = config.term_prompt(st.session_state.selected_term, st.session_state.selected_context, term_list)
|
| 198 |
-
initial_context = {
|
| 199 |
-
"role": "system",
|
| 200 |
-
"content": updated_prompt
|
| 201 |
-
}
|
| 202 |
# Replace the initial context in display_messages with the updated prompt
|
| 203 |
-
st.session_state.display_messages
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
# Get user input
|
| 206 |
-
prompt = st.chat_input("
|
| 207 |
|
| 208 |
# Input for new messages
|
| 209 |
if prompt:
|
|
@@ -214,7 +221,7 @@ if prompt:
|
|
| 214 |
|
| 215 |
# Function to reset all chat-related session state
|
| 216 |
def reset_chat_history():
|
| 217 |
-
st.session_state["display_messages"] = [
|
| 218 |
# Reset other chat-related session states if they exist
|
| 219 |
if 'selected_term' in st.session_state:
|
| 220 |
st.session_state.selected_term = None
|
|
@@ -256,12 +263,16 @@ with st.container(height=400, border=True):
|
|
| 256 |
st.session_state["display_messages"].append(
|
| 257 |
{"role": "assistant", "content": response}
|
| 258 |
)
|
|
|
|
|
|
|
| 259 |
except Exception as e:
|
| 260 |
st.error(f"An error occurred: {str(e)}")
|
|
|
|
| 261 |
|
| 262 |
# Add Clear Chat History button between container and warning message
|
| 263 |
if st.button("Clear Chat History"):
|
| 264 |
reset_chat_history()
|
|
|
|
| 265 |
|
| 266 |
st.markdown(config.warning_message, unsafe_allow_html=True)
|
| 267 |
|
|
|
|
| 13 |
import config
|
| 14 |
from openai import OpenAI
|
| 15 |
|
| 16 |
+
# Set up logging
|
| 17 |
+
logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
| 18 |
+
|
| 19 |
############################################################################################################
|
| 20 |
# Password protection
|
| 21 |
|
| 22 |
+
def check_credentials():
|
| 23 |
+
"""Returns `True` if the user had the correct username and password."""
|
| 24 |
+
|
| 25 |
+
def credentials_entered():
|
| 26 |
+
"""Checks whether the entered username and password are correct."""
|
| 27 |
+
if (
|
| 28 |
+
hmac.compare_digest(st.session_state["username"], st.secrets["username"]) and
|
| 29 |
+
hmac.compare_digest(st.session_state["password"], st.secrets["password"])
|
| 30 |
+
):
|
| 31 |
+
st.session_state["credentials_correct"] = True
|
| 32 |
+
del st.session_state["username"] # Don't store the username.
|
| 33 |
del st.session_state["password"] # Don't store the password.
|
| 34 |
else:
|
| 35 |
+
st.session_state["credentials_correct"] = False
|
| 36 |
|
| 37 |
+
# Return True if the credentials are validated.
|
| 38 |
+
if st.session_state.get("credentials_correct", False):
|
| 39 |
return True
|
| 40 |
|
| 41 |
+
# Show input for username and password.
|
| 42 |
+
st.text_input("Username", on_change=credentials_entered, key="username")
|
| 43 |
+
st.text_input("Password", type="password", on_change=credentials_entered, key="password")
|
| 44 |
+
|
| 45 |
+
if "credentials_correct" in st.session_state:
|
| 46 |
+
logging.warning("Invalid login attempt") # Log invalid login attempts
|
| 47 |
return False
|
| 48 |
|
| 49 |
+
if not check_credentials():
|
| 50 |
+
st.stop() # Do not continue if check_credentials is not True.
|
| 51 |
+
else:
|
| 52 |
+
logging.info("Successful login") # Log successful logins
|
| 53 |
|
| 54 |
############################################################################################################
|
| 55 |
# Streamlit app layout
|
|
|
|
| 64 |
st.title(config.app_title)
|
| 65 |
st.markdown(config.intro_para)
|
| 66 |
st.caption(config.app_author)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
st.sidebar.title(config.sidebar_title)
|
| 68 |
with st.sidebar:
|
| 69 |
with st.expander("Click here for instructions."):
|
|
|
|
| 73 |
# File Uploader in sidebar
|
| 74 |
|
| 75 |
# Load terms from a CSV file
|
|
|
|
| 76 |
def load_terms(file_input):
|
| 77 |
try:
|
| 78 |
if isinstance(file_input, str):
|
|
|
|
| 134 |
############################################################################################################
|
| 135 |
# Term Selection and session state
|
| 136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
# Initialize the session state variables for selected term, context, and display messages
|
| 138 |
if 'selected_term' not in st.session_state:
|
| 139 |
st.session_state.selected_term = None
|
| 140 |
if 'selected_context' not in st.session_state:
|
| 141 |
st.session_state.selected_context = None
|
| 142 |
if 'display_messages' not in st.session_state:
|
| 143 |
+
st.session_state.display_messages = []
|
| 144 |
|
| 145 |
# Initialize session states for the selected term, counter, and display flag
|
|
|
|
|
|
|
| 146 |
if 'display_term' not in st.session_state:
|
| 147 |
+
st.session_state.display_term = False
|
| 148 |
+
if 'initial_message_displayed' not in st.session_state:
|
| 149 |
+
st.session_state.initial_message_displayed = False
|
| 150 |
+
|
| 151 |
+
# Initialize state to track the previously selected term
|
| 152 |
+
if 'old_term' not in st.session_state:
|
| 153 |
+
st.session_state.old_term = None
|
| 154 |
|
| 155 |
# Dropdown menu for selecting a term
|
| 156 |
+
selected_term = st.selectbox('**SELECT FROM THE DROPDOWN MENU**', term_list)
|
| 157 |
+
|
| 158 |
if selected_term:
|
| 159 |
+
# If a new term is selected (including first time selection), reset or show the message
|
| 160 |
+
if selected_term != st.session_state.old_term:
|
| 161 |
+
user_message = f"What is one thing you know about '{selected_term}'? What do you want to know about it? This could include a definition, examples, misconceptions, associations with other course terms, opinions, etc."
|
| 162 |
+
st.session_state["display_messages"].append({"role": "user", "content": user_message})
|
| 163 |
+
# Update old_term in session state
|
| 164 |
+
st.session_state.old_term = selected_term
|
| 165 |
+
|
| 166 |
selected_context = terms.loc[terms['TERM'] == selected_term, 'CONTEXT'].values[0]
|
| 167 |
st.session_state.selected_term = selected_term
|
| 168 |
st.session_state.selected_context = selected_context
|
| 169 |
st.session_state.display_term = True
|
| 170 |
+
|
|
|
|
|
|
|
| 171 |
# Update the prompt for the API
|
| 172 |
updated_prompt = config.term_prompt(st.session_state.selected_term, st.session_state.selected_context, term_list)
|
| 173 |
+
|
| 174 |
+
else:
|
| 175 |
+
# If nothing is selected or the selection is cleared, reset the old_term
|
| 176 |
+
st.session_state.old_term = None
|
|
|
|
|
|
|
| 177 |
|
| 178 |
# Display the selected term and its context
|
| 179 |
if st.session_state.display_term and st.session_state.selected_term:
|
| 180 |
st.header(st.session_state.selected_term)
|
| 181 |
+
|
| 182 |
+
with st.expander("INSTRUCTIONS FOR STUDENTS:"):
|
| 183 |
+
st.markdown(config.instructions)
|
| 184 |
+
with st.expander("**INSTRUCTORS**: For a look at the current terms file driving the interaction, click here:"):
|
| 185 |
+
st.markdown("This is the terms.csv file that drives the interaction. You can edit this file to change the terms and context that the chatbot uses. You may add any term or phrase. You may leave the context blank if you prefer or you can add anything relevant that the GPT does not normally know about the term. This may include relevant learning objectives, course examples, notable scientists, assessment dates, syllabus information, etc.")
|
| 186 |
+
st.table(df)
|
| 187 |
+
with st.expander("**INSTRUCTORS**: For a look at the prompt driving the chatbot, click here:"):
|
| 188 |
+
prompt_text = config.term_prompt(st.session_state.selected_term, st.session_state.selected_context, term_list)
|
| 189 |
+
st.markdown(prompt_text)
|
| 190 |
|
| 191 |
############################################################################################################
|
| 192 |
# ChatGPT
|
|
|
|
| 198 |
st.session_state["openai_model"] = config.ai_model
|
| 199 |
|
| 200 |
if "display_messages" not in st.session_state:
|
| 201 |
+
st.session_state.display_messages = []
|
| 202 |
|
| 203 |
# Update initial_context with the latest selected term and context
|
| 204 |
if st.session_state.get('selected_term') and st.session_state.get('selected_context'):
|
| 205 |
updated_prompt = config.term_prompt(st.session_state.selected_term, st.session_state.selected_context, term_list)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
# Replace the initial context in display_messages with the updated prompt
|
| 207 |
+
if st.session_state.display_messages:
|
| 208 |
+
st.session_state.display_messages[0]["content"] = updated_prompt
|
| 209 |
+
else:
|
| 210 |
+
st.session_state.display_messages = [{"role": "system", "content": updated_prompt}]
|
| 211 |
|
| 212 |
# Get user input
|
| 213 |
+
prompt = st.chat_input("What do you know? What do you want to know?")
|
| 214 |
|
| 215 |
# Input for new messages
|
| 216 |
if prompt:
|
|
|
|
| 221 |
|
| 222 |
# Function to reset all chat-related session state
|
| 223 |
def reset_chat_history():
|
| 224 |
+
st.session_state["display_messages"] = []
|
| 225 |
# Reset other chat-related session states if they exist
|
| 226 |
if 'selected_term' in st.session_state:
|
| 227 |
st.session_state.selected_term = None
|
|
|
|
| 263 |
st.session_state["display_messages"].append(
|
| 264 |
{"role": "assistant", "content": response}
|
| 265 |
)
|
| 266 |
+
logging.info(f"User prompt: {prompt}") # Log user prompts
|
| 267 |
+
logging.info(f"Assistant response: {response}") # Log assistant responses
|
| 268 |
except Exception as e:
|
| 269 |
st.error(f"An error occurred: {str(e)}")
|
| 270 |
+
logging.exception(f"Error generating response: {e}") # Log errors
|
| 271 |
|
| 272 |
# Add Clear Chat History button between container and warning message
|
| 273 |
if st.button("Clear Chat History"):
|
| 274 |
reset_chat_history()
|
| 275 |
+
logging.info("Chat history cleared") # Log when chat history is cleared
|
| 276 |
|
| 277 |
st.markdown(config.warning_message, unsafe_allow_html=True)
|
| 278 |
|