Streamlit表单提交后用户输入重复显示问题求助
问题描述
- 预期流程:用户输入「指定城市之一的太阳能」,机器人展示表单提示输入所需数据;用户提交后,机器人显示「太阳能为XX数值」。
- 实际问题:点击提交后,机器人会重复用户最初的「XX城市太阳能」消息,再显示太阳能数值。
问题代码
import os import streamlit as st from displayer import bot_template, user_template from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.schema import SystemMessage, HumanMessage, AIMessage from ML.Ml import CityWeatherData def init(): load_dotenv() # Loading OpenAI API key if os.getenv("OPENAI_API_KEY") is None or os.getenv("OPENAI_API_KEY") == "": print("OPENAI_API_KEY is not set yet") exit(1) else: print("OPENAI_API_KEY is set") def main(): init() # Initialize LangChain Chat chat = ChatOpenAI(temperature=0) if "messages" not in st.session_state: st.session_state.messages = [ SystemMessage(content="You are a helpful assistant.") ] st.header("Green Optimizer 🤖") with st.sidebar: # CHATTING CODE user_input = st.text_input("Enter your message:") cities = "jeddah", "skaka", "riyadh", "dammam" if user_input: st.session_state.messages.append(HumanMessage(content=user_input)) with st.spinner("Thinking.."): if any(city in user_input.lower() for city in cities): user_city = None for city in cities: if city in user_input.lower(): user_city = city break # If city name is found, proceed with solar energy analysis if user_city: # Display the form for user input st.write(f"Welcome! Please enter the following information for {user_city.capitalize()}:") with st.form(key='weather_form'): ALLSKY = st.number_input("Enter ALLSKY:") CLRSKY = st.number_input("Enter CLRSKY:") pressure = st.number_input("Enter pressure:") temperature = st.number_input("Enter temperature:") moisture = st.number_input("Enter moisture:") submit_button = st.form_submit_button(label='Submit') # If the form is submitted, calculate and display the result if submit_button: # Create CityWeatherData instance weather_data = CityWeatherData(city=user_city) # Analyze weather for the selected city solar_energy = weather_data.analyze_weather( ALLSKY=ALLSKY, CLRSKY=CLRSKY, temperature=temperature, pressure=pressure, moisture=moisture ) # Append the user and AI messages to the conversation st.session_state.messages.append(AIMessage(content=f"The Solar Energy in {user_city.capitalize()} is: {solar_energy}")) else: # If no valid city name is found, proceed with regular chat response = chat(st.session_state.messages) st.session_state.messages.append(AIMessage(content=response.content)) else: # If no city name is mentioned, proceed with regular chat response = chat(st.session_state.messages) st.session_state.messages.append(AIMessage(content=response.content)) # Displaying all the messages the user had by fetching them messages = st.session_state.get("messages", []) # Looping through all the messages, if 1 user(odd number) display it from the human position. # If two users(even number) display it from the bot position. for i, msgs in enumerate(messages[1:]): if i % 2 == 0: st.markdown(user_template.replace("{{MSG}}", msgs.content), unsafe_allow_html=True) else: st.markdown(bot_template.replace("{{MSG}}", msgs.content), unsafe_allow_html=True) if __name__ == '__main__': main()
解决方案
问题根源
Streamlit每次触发页面刷新(比如提交表单)时,会重新执行整个脚本,之前的user_input值会被保留,导致代码再次进入if user_input:分支,重复将用户初始查询消息添加到对话历史中。
修改后代码
import os import streamlit as st from displayer import bot_template, user_template from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.schema import SystemMessage, HumanMessage, AIMessage from ML.Ml import CityWeatherData def init(): load_dotenv() # Loading OpenAI API key if os.getenv("OPENAI_API_KEY") is None or os.getenv("OPENAI_API_KEY") == "": print("OPENAI_API_KEY is not set yet") exit(1) else: print("OPENAI_API_KEY is set") def main(): init() # Initialize LangChain Chat chat = ChatOpenAI(temperature=0) # 初始化对话历史和流程状态 if "messages" not in st.session_state: st.session_state.messages = [ SystemMessage(content="You are a helpful assistant.") ] if "current_city" not in st.session_state: st.session_state.current_city = None st.header("Green Optimizer 🤖") with st.sidebar: user_input = st.text_input("Enter your message:") cities = ("jeddah", "skaka", "riyadh", "dammam") # 仅在未处理城市查询时,处理用户输入 if user_input and st.session_state.current_city is None: st.session_state.messages.append(HumanMessage(content=user_input)) with st.spinner("Thinking.."): user_city = None for city in cities: if city in user_input.lower(): user_city = city break if user_city: # 标记进入城市查询流程 st.session_state.current_city = user_city else: # 常规聊天逻辑 response = chat(st.session_state.messages) st.session_state.messages.append(AIMessage(content=response.content)) # 如果处于城市查询流程,单独显示表单 if st.session_state.current_city: user_city = st.session_state.current_city st.write(f"Welcome! Please enter the following information for {user_city.capitalize()}:") with st.form(key='weather_form'): ALLSKY = st.number_input("Enter ALLSKY:") CLRSKY = st.number_input("Enter CLRSKY:") pressure = st.number_input("Enter pressure:") temperature = st.number_input("Enter temperature:") moisture = st.number_input("Enter moisture:") submit_button = st.form_submit_button(label='Submit') if submit_button: weather_data = CityWeatherData(city=user_city) solar_energy = weather_data.analyze_weather( ALLSKY=ALLSKY, CLRSKY=CLRSKY, temperature=temperature, pressure=pressure, moisture=moisture ) # 添加AI结果到对话历史 st.session_state.messages.append(AIMessage(content=f"The Solar Energy in {user_city.capitalize()} is: {solar_energy}")) # 重置流程状态,恢复正常输入 st.session_state.current_city = None # 渲染对话历史 messages = st.session_state.get("messages", []) for i, msgs in enumerate(messages[1:]): if i % 2 == 0: st.markdown(user_template.replace("{{MSG}}", msgs.content), unsafe_allow_html=True) else: st.markdown(bot_template.replace("{{MSG}}", msgs.content), unsafe_allow_html=True) if __name__ == '__main__': main()
修改要点
- 新增
st.session_state.current_city状态变量,标记是否处于城市太阳能查询流程中 - 将用户输入处理与表单展示逻辑分离,仅在未处理城市查询时,才处理用户输入并添加消息到历史
- 表单提交完成后重置
current_city,恢复正常输入状态,避免重复触发原始输入逻辑
内容的提问来源于stack exchange,提问作者Eva
相关产品推荐
相关产品推荐

