arize_demo / app.py
Cam
adjusted app.py due to initiatlization error
604eb35
# Modify the init_app function in app.py to ensure proper initialization and handling of errors:
def init_app():
"""Initialize everything just once using st.session_state."""
# Initialize empty collections to prevent KeyError
if "chat_history" not in st.session_state:
st.session_state["chat_history"] = []
# Create a flag for initialization attempts
if "initialization_attempted" not in st.session_state:
st.session_state["initialization_attempted"] = False
if "initialized" not in st.session_state:
st.session_state["initialization_attempted"] = True
try:
# Add key presence checks before starting initialization
st.session_state["initialized"] = False # Mark as not initialized until complete
logger.info("Starting app initialization")
# Load settings
settings = Settings()
st.session_state["settings"] = settings
# (1) instrumentation (if needed)
with st.spinner("Setting up instrumentation..."):
tracer_provider = setup_instrumentation()
st.session_state["tracer"] = tracer_provider.get_tracer("llamaindex_app")
logger.info("Instrumentation setup complete")
# (2) OpenAI client
with st.spinner("Initializing OpenAI client..."):
openai_client = init_openai_client()
st.session_state["openai_client"] = openai_client
logger.info("OpenAI client initialized")
# (3) index manager & query engine
with st.spinner("Loading index and query engine..."):
# Create these objects explicitly
index_manager = IndexManager(openai_client=openai_client)
query_engine = index_manager.get_query_engine()
# Store them in session_state
st.session_state["index_manager"] = index_manager
st.session_state["query_engine"] = query_engine
logger.info("Index and query engine loaded")
# (4) classifier
with st.spinner("Initializing query classifier..."):
# Create classifier only when we are sure query_engine exists
if "query_engine" in st.session_state:
classifier = QueryClassifier(
query_engine=st.session_state["query_engine"],
openai_client=openai_client
)
st.session_state["classifier"] = classifier
logger.info("Query classifier initialized")
else:
raise ValueError("Query engine not initialized properly")
st.session_state["initialized"] = True # Now mark as fully initialized
logger.info("App initialization complete")
st.success("App initialized successfully!")
except Exception as e:
st.error(f"Failed to initialize app: {str(e)}")
logger.error(f"Initialization error: {str(e)}", exc_info=True)
st.session_state["initialization_error"] = str(e)
return False
return True
return "initialized" in st.session_state and st.session_state["initialized"]
# Modify the main function to handle errors more gracefully:
def main():
"""Main Streamlit app function."""
st.title("Assurant 10-K Analysis & Risk Assessment App")
# Sidebar with app info
with st.sidebar:
st.subheader("About this app")
st.write("""
This application analyzes Assurant's 10-K reports and provides risk assessment.
You can ask questions about:
- Assurant's financial performance
- Risk factors
- Business operations
- Market trends
""")
# Debug section in sidebar
if st.checkbox("Show debug info"):
st.subheader("Debug Information")
st.write("Session State Keys:")
for key in st.session_state:
st.write(f"- {key}: {'Present' if st.session_state[key] is not None else 'None'}")
st.write("Python Path:")
for path in sys.path:
st.write(f"- {path}")
# Display environment variables (without sensitive values)
st.write("Environment Variables:")
safe_vars = {
k: (v if not any(secret in k.lower() for secret in ["key", "secret", "password", "token"]) else "****")
for k, v in os.environ.items()
if k.startswith(("OPENAI_", "LLAMAINDEX_"))
}
for k, v in safe_vars.items():
st.write(f"- {k}: {v}")
# Also display settings from the Settings class
if "settings" in st.session_state:
settings = st.session_state["settings"]
st.write("App Settings:")
st.write(f"- OpenAI Model: {settings.OPENAI_MODEL}")
st.write(f"- OpenAI Base URL: {settings.OPENAI_BASE_URL if settings.OPENAI_BASE_URL else 'Default API URL'}")
if settings.OPENAI_ORG_ID:
st.write(f"- OpenAI Organization: {settings.OPENAI_ORG_ID}")
# Initialize the app
initialization_status = init_app()
if initialization_status is False:
st.error(f"Initialization failed: {st.session_state.get('initialization_error', 'Unknown error')}")
st.warning("Please check your environment variables and connection settings.")
return
# Safety check - if we've attempted initialization but still don't have key components
if st.session_state.get("initialization_attempted", False) and not st.session_state.get("initialized", False):
st.warning("The application is still initializing or had problems during initialization. Please wait or refresh the page.")
return
# Query section - Only show if properly initialized
if st.session_state.get("initialized", False):
st.subheader("Ask a question about Assurant's 10-K")
user_question = st.text_input("Your question:", placeholder="e.g., How did Assurant perform last quarter?")
submit = st.button("Submit Question")
if submit and user_question.strip():
# Safely retrieve references from st.session_state with error handling
try:
# Check that all required components exist
required_keys = ["query_engine", "classifier", "tracer"]
missing_keys = [key for key in required_keys if key not in st.session_state]
if missing_keys:
st.error(f"Missing required components: {', '.join(missing_keys)}")
return
query_engine = st.session_state["query_engine"]
classifier = st.session_state["classifier"]
tracer = st.session_state["tracer"]
session_id = str(uuid.uuid4())
with st.spinner("Analyzing your question..."):
# Log the question being processed
logger.info(f"Processing query: {user_question}")
response, error = process_interaction(
query_engine,
classifier,
tracer,
user_question,
session_id
)
# Store in st.session_state so we can display entire conversation
if error:
st.session_state["chat_history"].append(("user", user_question))
st.session_state["chat_history"].append(("assistant", f"Error: {error}"))
st.error(f"Error: {error}")
logger.error(f"Query processing error: {error}")
else:
st.session_state["chat_history"].append(("user", user_question))
st.session_state["chat_history"].append(("assistant", response.response))
logger.info("Query processed successfully")
# If there are any sources
if getattr(response, "source_nodes", None):
source_text = "\n".join(
f"- {node.metadata.get('file_name', 'Unknown source')}"
for node in response.source_nodes
)
st.session_state["chat_history"].append(("assistant_sources", source_text))
logger.info(f"Found {len(response.source_nodes)} source nodes")
except Exception as e:
st.error(f"Error processing your question: {str(e)}")
logger.error(f"Process interaction error: {str(e)}", exc_info=True)
st.session_state["chat_history"].append(("user", user_question))
st.session_state["chat_history"].append(("assistant", f"Error processing your question: {str(e)}"))
# Display the chat history
st.subheader("Conversation")
history_container = st.container()
with history_container:
for idx, (role, content) in enumerate(st.session_state.get("chat_history", [])):
if role == "user":
st.markdown(f"**You**: {content}")
elif role == "assistant":
st.markdown(f"**Assistant**: {content}")
elif role == "assistant_sources":
with st.expander("View Sources"):
st.markdown(content)
# Add a separator between conversations
if idx < len(st.session_state.get("chat_history", [])) - 1 and role == "assistant":
st.markdown("---")