Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from openai import OpenAI | |
| from pymongo.mongo_client import MongoClient | |
| from pymongo.server_api import ServerApi | |
| from datetime import datetime | |
| import random | |
| st.set_page_config( | |
| page_title="Climate Action", | |
| page_icon="π", | |
| initial_sidebar_state="expanded", | |
| layout="wide" | |
| ) | |
| st.markdown( | |
| """ <style> | |
| div[role="radiogroup"] > :first-child{ | |
| display: none !important; | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True | |
| ) | |
| ### Setting up the session state | |
| def generate_tokens(response): | |
| # for deepseek | |
| for token in response: | |
| if hasattr(token, 'choices') and token.choices: | |
| content = token.choices[0].delta.content | |
| if content: | |
| yield content | |
| def format_personalization(text): | |
| try: | |
| for key, value in st.session_state.items(): | |
| text = text.replace(f"[{key.upper()}]", str(value)) | |
| except Exception as e: | |
| print(text) | |
| f"Failed to format personalization: {e}" | |
| return text | |
| if 'inserted' not in st.session_state: | |
| with open('base.txt', 'r') as file: | |
| st.session_state.base_text = file.read() | |
| with open('knowledge.txt', 'r') as file: | |
| st.session_state.knowledge_text = file.read() | |
| with open('personalization.txt', 'r') as file: | |
| st.session_state.personalization_text = file.read() | |
| # web app state | |
| st.session_state.gotit = False | |
| st.session_state.submitted = False | |
| st.session_state.inserted = 0 | |
| st.session_state["model"] = "openai/gpt-4.1" | |
| st.session_state.max_messages = 50 | |
| st.session_state.messages = [] | |
| st.session_state.user_data = {} | |
| # user info state | |
| st.session_state.fields = [ | |
| 'climate_actions', 'age', 'gender', 'education', 'residence', 'property', 'car', | |
| 'politics', 'impact_open', 'ev', | |
| 'fossil', 'aerosol', 'diet', 'recycling', | |
| 'user_id', 'random_pid' | |
| ] | |
| for field in st.session_state.fields: | |
| st.session_state[field] = '' | |
| st.session_state.user_id = str(random.randint(100000, 999999)) | |
| st.session_state.random_pid = st.query_params['id'] if 'id' in st.query_params else "0" | |
| st.session_state.recycling = 0 | |
| st.session_state.start_time = datetime.now() | |
| st.session_state.convo_start_time = '' | |
| if 'p' not in st.query_params: | |
| st.query_params['p'] = 't' | |
| if 'id' not in st.query_params: | |
| st.query_params['id'] = st.session_state.random_pid | |
| def setup_messages(): | |
| # t = personalization, k = knowledge, f = formatting, n = no chat | |
| if st.query_params["p"] == "f" or st.query_params["p"] == "n": | |
| st.session_state.system_message = st.session_state.base_text | |
| elif st.query_params["p"] == "k": | |
| st.session_state.system_message = st.session_state.knowledge_text | |
| elif st.query_params["p"] == "t": | |
| st.session_state.system_message = format_personalization(st.session_state.personalization_text) | |
| st.session_state.messages = [{ "role": "system", "content": st.session_state.system_message}] | |
| st.session_state.convo_start_time = datetime.now() | |
| client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=st.secrets["OPENROUTER_API_KEY"]) | |
| ### App interface | |
| with st.sidebar: | |
| st.markdown("# Let's talk climate action!") | |
| st.markdown(f""" | |
| {"β" if st.session_state.submitted else "β"} **Step 1. Complete a form** | |
| {"β" if len(st.session_state.messages) > 0 else "β"} **Step 2. Type in the chat box to start a conversation** | |
| π± You should ask a climate change related question like: | |
| - *What are the most effective actions to reduce my carbon emissions?* | |
| - *What's better for the environment: a year of vegetarianism or skipping one transatlantic flight?* | |
| - *How do the emissions saved by switching to an EV compare to recycling for a year in terms of trees planted?* | |
| β Do not share any personal information (e.g., name or address). | |
| β Do not use AI tools to generate your responses; write them yourself. | |
| ## β οΈ You must respond **at least 5 times** before you will see a *Submit Interaction* button. You can continue before submitting, but **you must click *Submit Interaction* and enter your WORD into the survey to receive compensation**. The WORD will only appear after you click the *Submit Interaction* button. | |
| β If you encounter any technical issues, please let us know. It might sometimes take 30 seconds or more to generate a response, so please be patient. | |
| {"β" if st.session_state.inserted > 1 else "β"} **Step 3. Press the *Submit Interaction* button to get your WORD** | |
| βΊ You can always return to this panel by clicking the arrow on the top left. | |
| {"π **All done! Please enter your WORD in the survey.**" if st.session_state.inserted > 1 else ""} | |
| """) | |
| if st.session_state.gotit == False or st.session_state.submitted == False: | |
| st.session_state.gotit = st.button("Let's start!", key=None, help=None, use_container_width=True) | |
| def form(): | |
| st.markdown("**Please answer every question to proceed.**") | |
| st.session_state.age = st.text_input("How old are you in years?") | |
| st.session_state.gender = st.radio("Do you describe yourself as a man, a woman, or in some other way?", | |
| ['','Man', 'Woman', 'Other']) | |
| st.session_state.education = st.radio("What is the highest level of education you completed?", | |
| ['', | |
| 'Did not graduate high school', | |
| 'High school graduate, GED, or alternative', | |
| 'Some college, or associates degree', | |
| "Bachelor's (college) degree or equivalent", | |
| "Graduate degree (e.g., Master's degree, MBA)", | |
| 'Doctorate degree (e.g., PhD, MD)']) | |
| st.session_state.politics = st.radio('What is your political orientation?', ['', 'Extremely liberal', 'Liberal', 'Slightly liberal', 'Moderate', 'Slightly conservative', 'Conservative', 'Extremely conservative']) | |
| st.session_state.residence = st.radio("What type of a community do you live in?", | |
| ['', 'Urban','Suburban','Rural','Other']) | |
| st.session_state.property = st.radio("Do you own or rent the home in which you live?", | |
| ['', 'Own', 'Rent', 'Neither (I live rent-free)', 'Other' ]) | |
| st.session_state.car = st.radio("Do you own or lease a car?", | |
| ['', 'Own', 'Lease', 'Neither (I do not own or lease a car)']) | |
| st.session_state.climate_actions = st.text_area('Please describe any actions you are taking to address climate change? Write *None* if you are not taking any.') | |
| st.session_state.impact_open = st.text_area('What do you believe is the single most effective action you can take to reduce carbon emissions that contribute to climate change?') | |
| st.session_state.recycling = st.slider('What percentage of plastic produced gets recycled?', 0, 100, value=0) | |
| st.markdown("**Do you agree or disagree with the following statements?**") | |
| st.session_state.ev = st.radio("Electric vehicles don't have enough range to handle daily travel demands.", ["", "Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]) | |
| st.session_state.fossil = st.radio('The fossil fuel industry is trying to shift the blame away from themselves by emphasizing the importance of individual climate action.', ["", "Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]) | |
| st.session_state.aerosol = st.radio('The use of aerosol spray cans is a major cause of climate change.', ["", "Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]) | |
| st.session_state.diet = st.radio('Lab-grown meat produces up to 25 times more CO2 than real meat.', ["", "Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]) | |
| columns_form = st.columns((1,1,1)) | |
| with columns_form[2]: | |
| submitted = st.button("Proceed",use_container_width=True, | |
| help = 'Make sure you answer every question', | |
| disabled = not (all(st.session_state[field] != '' for field in st.session_state.fields) and st.session_state.recycling != 0)) | |
| if submitted: | |
| st.session_state.user_data = {key: st.session_state[key] for key in st.session_state.fields} | |
| st.session_state.user_data["model"] = st.session_state["model"] | |
| st.session_state.user_data["condition"] = st.query_params['p'] | |
| st.session_state.user_data["start_time"] = st.session_state.start_time | |
| st.session_state.user_data["inserted"] = st.session_state.inserted | |
| st.session_state.user_data["submission_time"] = datetime.now() | |
| #with MongoClient(st.secrets["mongo"],server_api=ServerApi('1')) as client: | |
| # db = client.chat | |
| # collection = db.app | |
| # user_data = st.session_state.user_data | |
| # collection.insert_one(user_data) | |
| st.session_state.inserted += 1 | |
| st.session_state.submitted = True | |
| setup_messages() | |
| st.rerun() | |
| if st.session_state.gotit and st.session_state.submitted == False: | |
| form() | |
| for message in st.session_state.messages: | |
| if message['role']!='system': | |
| with st.chat_message(message["role"]): | |
| st.markdown(message["content"]) | |
| if len(st.session_state.messages) >= st.session_state.max_messages: | |
| st.info( | |
| "You have reached the limit of messages for this conversation. Please end and submit the conversation." | |
| ) | |
| elif st.session_state.submitted == False: | |
| pass | |
| elif st.session_state.inserted > 1: | |
| st.markdown("## Copy your WORD!") | |
| st.markdown('**Your WORD to proceed with the study is:**') | |
| st.markdown(f'## POTATOES') | |
| st.markdown('**Please copy the WORD and enter it into the box at the bottom of the page.**') | |
| st.markdown('β **This is not the end of the study.**') | |
| elif st.query_params["p"] == "n": | |
| st.markdown("""**You have (randomly) not been selected to have a conversation with the chatbot.** | |
| Please press *Submit Interaction* to get your WORD to proceed with the study. | |
| """) | |
| columns = st.columns((1,1,1)) | |
| with columns[2]: | |
| if st.button("Submit Interaction",use_container_width=True,type="primary"): | |
| keys = ["inserted", "messages", "convo_start_time"] | |
| st.session_state.user_data.update({key: st.session_state[key] for key in keys}) | |
| st.session_state.user_data["convo_end_time"] = datetime.now() | |
| with MongoClient(st.secrets["mongo"],server_api=ServerApi('1')) as client: | |
| db = client.chat | |
| collection = db.app | |
| user_data = st.session_state.user_data | |
| collection.insert_one(user_data) | |
| st.session_state.inserted += 1 | |
| done = True | |
| setup_messages() | |
| st.rerun() | |
| elif prompt := st.chat_input("Ask a question about climate action..."): | |
| st.session_state.messages.append({"role": "user", "content": prompt}) | |
| with st.chat_message("user"): | |
| st.markdown(prompt) | |
| with st.chat_message("assistant"): | |
| try: | |
| stream = client.chat.completions.create( | |
| model=st.session_state["model"], | |
| messages=[ | |
| {"role": m["role"], "content": m["content"]} | |
| for m in st.session_state.messages | |
| ], | |
| stream=True | |
| ) | |
| response = st.write_stream(stream) | |
| st.session_state.messages.append( | |
| {"role": "assistant", "content": response} | |
| ) | |
| except: | |
| rate_limit_message = """ | |
| An error has occured or you've reached the maximum conversation length. Please submit the conversation. | |
| """ | |
| st.session_state.messages.append( | |
| {"role": "assistant", "content": rate_limit_message} | |
| ) | |
| st.session_state.max_messages = len(st.session_state.messages) | |
| st.rerun() | |
| if len(st.session_state.messages) > 10 or st.session_state.max_messages == len(st.session_state.messages): | |
| columns = st.columns((1,1,1)) | |
| with columns[2]: | |
| if st.button("Submit Interaction",use_container_width=True, type="primary"): | |
| keys = ["inserted", "messages", "convo_start_time"] | |
| st.session_state.user_data.update({key: st.session_state[key] for key in keys}) | |
| st.session_state.user_data["convo_end_time"] = datetime.now() | |
| with MongoClient(st.secrets["mongo"],server_api=ServerApi('1')) as client: | |
| db = client.chat | |
| collection = db.app | |
| user_data = st.session_state.user_data | |
| collection.insert_one(user_data) | |
| st.session_state.inserted += 1 | |
| done = True | |
| setup_messages() | |
| st.rerun() | |