Spaces:
Running
Running
File size: 3,036 Bytes
6ba3ef3 be81d7c 6ba3ef3 4eda25e 6f598ab 7ab3f4b 4eda25e 6ba3ef3 4eda25e 6ba3ef3 4eda25e 6ba3ef3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | """FinChat - Streamlit chat UI.
Run from the project root:
streamlit run app.py
"""
import streamlit as st
from src.rag import answer, available_companies, ensure_index
st.set_page_config(
page_title="FinChat",
page_icon="π¬",
layout="centered",
initial_sidebar_state="expanded",
)
st.title("π¬ FinChat")
st.caption(
"Ask questions about companies' SEC 10-K filings. "
"Every answer is grounded in the filings, with sources you can inspect."
)
# On a fresh deployment (e.g. Hugging Face Spaces) the vector store won't exist
# yet -- build it once on first load. On later runs this is a fast no-op.
with st.spinner("Preparing the knowledge base (first run only, please wait)β¦"):
ensure_index()
# --- sidebar: which companies are available ---------------------------------
with st.sidebar:
st.header("π Companies loaded")
for ticker, name in available_companies():
st.markdown(f"- **{ticker}** β {name}")
st.caption("Source: recent SEC 10-K filings (FY2021β2023).")
# --- starter questions (clickable examples) ---------------------------------
STARTER_QUESTIONS = [
"What products does Apple sell?",
"What does NVIDIA design and sell?",
"What are Boeing's business segments?",
"What are the main risks AMD identifies?",
]
# --- chat history -----------------------------------------------------------
if "messages" not in st.session_state:
st.session_state.messages = []
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
# Clickable examples, shown only until the first question is asked.
if not st.session_state.messages and "pending" not in st.session_state:
st.markdown("**Try one of these to get started:**")
cols = st.columns(2)
for i, example in enumerate(STARTER_QUESTIONS):
if cols[i % 2].button(example, use_container_width=True):
st.session_state.pending = example
st.rerun()
# --- new question -----------------------------------------------------------
# A question can arrive from the chat box or from a starter button.
prompt = st.chat_input("e.g. What were AMD's main risk factors?") or st.session_state.pop("pending", None)
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
with st.spinner("Searching the filings..."):
result = answer(prompt)
st.markdown(result["answer"])
if result["routed_to"]:
st.caption(f"π Routed retrieval to: **{result['routed_to']}**")
with st.expander(f"π Sources ({len(result['sources'])})"):
for i, doc in enumerate(result["sources"], 1):
st.markdown(f"**[{i}] {doc.metadata.get('source', '')}**")
st.write(doc.page_content[:500] + "β¦")
st.session_state.messages.append(
{"role": "assistant", "content": result["answer"]}
)
|