mohmad017's picture
Index Documents button always visible
7313b2c
Raw
History Blame Contribute Delete
5.66 kB
import uuid
import os
import sys
import tempfile
import streamlit as st
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
sys.path.insert(0, os.path.dirname(__file__))
st.set_page_config(
page_title="Research Assistant",
page_icon="🔬",
layout="wide",
)
if "thread_id" not in st.session_state:
st.session_state.thread_id = str(uuid.uuid4())
if "messages" not in st.session_state:
st.session_state.messages = []
if "threads" not in st.session_state:
st.session_state.threads = [st.session_state.thread_id]
if "titles" not in st.session_state:
st.session_state.titles = {}
if "last_meta" not in st.session_state:
st.session_state.last_meta = {}
if "docs_ingested" not in st.session_state:
st.session_state.docs_ingested = []
@st.cache_resource(show_spinner="Loading agent...")
def load_agent():
from src.agents.graph import get_graph
return get_graph()
with st.sidebar:
st.title("🔬 Research Assistant")
st.caption("LangGraph · RAG · Multi-Agent")
st.divider()
st.subheader("📚 Upload Documents")
uploaded = st.file_uploader(
"Upload PDFs",
type=["pdf"],
accept_multiple_files=True,
)
if st.button("📥 Index Documents", type="primary"):
if uploaded:
from src.agents.graph import ingest_pdf
bar = st.progress(0)
for i, pdf in enumerate(uploaded):
meta = ingest_pdf(
pdf.getvalue(),
thread_id=st.session_state.thread_id,
filename=pdf.name,
)
st.session_state.docs_ingested.append(pdf.name)
bar.progress((i + 1) / len(uploaded))
st.success(f"✅ Indexed {len(uploaded)} document(s)")
else:
st.warning("Please upload PDFs first.")
if st.session_state.docs_ingested:
st.caption(f"{len(st.session_state.docs_ingested)} doc(s) indexed")
for name in st.session_state.docs_ingested[-5:]:
st.caption(f" 📄 {name}")
st.divider()
st.subheader("💬 Chats")
if st.button("➕ New Chat"):
new_id = str(uuid.uuid4())
st.session_state.thread_id = new_id
st.session_state.messages = []
st.session_state.threads.insert(0, new_id)
st.rerun()
for tid in st.session_state.threads[:10]:
title = st.session_state.titles.get(tid, f"Chat {tid[:6]}")
active = "▶ " if tid == st.session_state.thread_id else " "
if st.button(f"{active}{title}", key=f"t_{tid}", use_container_width=True):
st.session_state.thread_id = tid
try:
graph = load_agent()
state = graph.get_state({"configurable": {"thread_id": tid}})
st.session_state.messages = [
{
"role": "user" if isinstance(m, HumanMessage) else "assistant",
"content": m.content,
}
for m in state.values.get("messages", [])
if isinstance(m, (HumanMessage, AIMessage)) and m.content
]
except Exception:
st.session_state.messages = []
st.rerun()
st.title("🔬 Research Assistant")
if st.session_state.last_meta:
m = st.session_state.last_meta
model = m.get("model_used", "")
label = "⚡ Fast (8B)" if "8b" in model else "🧠 Smart (70B)"
qtype = m.get("query_type", "?")
st.caption(f"{label} · {qtype} · {m.get('latency_ms', 0):.0f}ms")
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
user_input = st.chat_input("Ask anything about your documents...")
if user_input:
if st.session_state.thread_id not in st.session_state.titles:
st.session_state.titles[st.session_state.thread_id] = user_input[:28]
st.session_state.messages.append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.markdown(user_input)
graph = load_agent()
config = {"configurable": {"thread_id": st.session_state.thread_id}}
with st.chat_message("assistant"):
tool_box = [None]
def stream():
for chunk, _ in graph.stream(
{"messages": [HumanMessage(content=user_input)]},
config=config,
stream_mode="messages",
):
if isinstance(chunk, ToolMessage) and tool_box[0] is None:
tool_box[0] = st.status("🔧 Using tools...", expanded=True)
if isinstance(chunk, AIMessage) and chunk.content:
content = chunk.content
for prefix in ["simple", "complex", "calc"]:
if content.lower().startswith(prefix):
content = content[len(prefix):]
yield content
answer = st.write_stream(stream())
if tool_box[0]:
tool_box[0].update(label="✅ Done", state="complete", expanded=False)
try:
state = graph.get_state(config)
st.session_state.last_meta = {
"query_type": state.values.get("query_type"),
"model_used": state.values.get("model_used"),
"latency_ms": state.values.get("latency_ms"),
}
except Exception:
pass
st.session_state.messages.append({"role": "assistant", "content": answer})
st.rerun()