Dinesh310 commited on
Commit
1ec32f4
·
verified ·
1 Parent(s): 383ee63

Create streamlit_app_N.py

Browse files
Files changed (1) hide show
  1. streamlit_app_N.py +172 -0
streamlit_app_N.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+
3
+ import streamlit as st
4
+ from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
5
+
6
+ from src.langraph_rag_backend import (
7
+ chatbot,
8
+ ingest_pdf,
9
+ retrieve_all_threads,
10
+ thread_document_metadata,
11
+ )
12
+
13
+
14
+ # =========================== Utilities ===========================
15
+ def generate_thread_id():
16
+ return uuid.uuid4()
17
+
18
+
19
+ def reset_chat():
20
+ thread_id = generate_thread_id()
21
+ st.session_state["thread_id"] = thread_id
22
+ add_thread(thread_id)
23
+ st.session_state["message_history"] = []
24
+
25
+
26
+ def add_thread(thread_id):
27
+ if thread_id not in st.session_state["chat_threads"]:
28
+ st.session_state["chat_threads"].append(thread_id)
29
+
30
+
31
+ def load_conversation(thread_id):
32
+ state = chatbot.get_state(config={"configurable": {"thread_id": thread_id}})
33
+ return state.values.get("messages", [])
34
+
35
+
36
+ # ======================= Session Initialization ===================
37
+ if "message_history" not in st.session_state:
38
+ st.session_state["message_history"] = []
39
+
40
+ if "thread_id" not in st.session_state:
41
+ st.session_state["thread_id"] = generate_thread_id()
42
+
43
+ if "chat_threads" not in st.session_state:
44
+ st.session_state["chat_threads"] = retrieve_all_threads()
45
+
46
+ if "ingested_docs" not in st.session_state:
47
+ st.session_state["ingested_docs"] = {}
48
+
49
+ add_thread(st.session_state["thread_id"])
50
+
51
+ thread_key = str(st.session_state["thread_id"])
52
+ thread_docs = st.session_state["ingested_docs"].setdefault(thread_key, {})
53
+ threads = st.session_state["chat_threads"][::-1]
54
+ selected_thread = None
55
+
56
+ # ============================ Sidebar ============================
57
+ st.sidebar.title("LangGraph PDF Chatbot")
58
+ st.sidebar.markdown(f"**Thread ID:** `{thread_key}`")
59
+
60
+ if st.sidebar.button("New Chat", use_container_width=True):
61
+ reset_chat()
62
+ st.rerun()
63
+
64
+ if thread_docs:
65
+ latest_doc = list(thread_docs.values())[-1]
66
+ st.sidebar.success(
67
+ f"Using `{latest_doc.get('filename')}` "
68
+ f"({latest_doc.get('chunks')} chunks from {latest_doc.get('documents')} pages)"
69
+ )
70
+ else:
71
+ st.sidebar.info("No PDF indexed yet.")
72
+
73
+ uploaded_pdfs = st.sidebar.file_uploader("Upload a PDF for this chat", type=["pdf"], accept_multiple_files=True)
74
+ if uploaded_pdfs:
75
+ for uploaded_pdf in uploaded_pdfs:
76
+ if uploaded_pdf.name in thread_docs:
77
+ st.sidebar.info(f"`{uploaded_pdf.name}` already processed for this chat.")
78
+ else:
79
+ with st.sidebar.status("Indexing PDF…", expanded=True) as status_box:
80
+ summary = ingest_pdf(
81
+ uploaded_pdf.getvalue(),
82
+ thread_id=thread_key,
83
+ filename=uploaded_pdf.name,
84
+ )
85
+ thread_docs[uploaded_pdf.name] = summary
86
+ status_box.update(label="✅ PDF indexed", state="complete", expanded=False)
87
+
88
+ st.sidebar.subheader("Past conversations")
89
+ if not threads:
90
+ st.sidebar.write("No past conversations yet.")
91
+ else:
92
+ for thread_id in threads:
93
+ if st.sidebar.button(str(thread_id), key=f"side-thread-{thread_id}"):
94
+ selected_thread = thread_id
95
+
96
+ # ============================ Main Layout ========================
97
+ st.title("Multi Utility Chatbot")
98
+
99
+ # Chat area
100
+ for message in st.session_state["message_history"]:
101
+ with st.chat_message(message["role"]):
102
+ st.text(message["content"])
103
+
104
+ user_input = st.chat_input("Ask about your document or use tools")
105
+
106
+ if user_input:
107
+ st.session_state["message_history"].append({"role": "user", "content": user_input})
108
+ with st.chat_message("user"):
109
+ st.text(user_input)
110
+
111
+ CONFIG = {
112
+ "configurable": {"thread_id": thread_key},
113
+ "metadata": {"thread_id": thread_key},
114
+ "run_name": "chat_turn",
115
+ }
116
+
117
+ with st.chat_message("assistant"):
118
+ status_holder = {"box": None}
119
+
120
+ def ai_only_stream():
121
+ for message_chunk, _ in chatbot.stream(
122
+ {"messages": [HumanMessage(content=user_input)]},
123
+ config=CONFIG,
124
+ stream_mode="messages",
125
+ ):
126
+ if isinstance(message_chunk, ToolMessage):
127
+ tool_name = getattr(message_chunk, "name", "tool")
128
+ if status_holder["box"] is None:
129
+ status_holder["box"] = st.status(
130
+ f"🔧 Using `{tool_name}` …", expanded=True
131
+ )
132
+ else:
133
+ status_holder["box"].update(
134
+ label=f"🔧 Using `{tool_name}` …",
135
+ state="running",
136
+ expanded=True,
137
+ )
138
+
139
+ if isinstance(message_chunk, AIMessage):
140
+ yield message_chunk.content
141
+
142
+ ai_message = st.write_stream(ai_only_stream())
143
+
144
+ if status_holder["box"] is not None:
145
+ status_holder["box"].update(
146
+ label="✅ Tool finished", state="complete", expanded=False
147
+ )
148
+
149
+ st.session_state["message_history"].append(
150
+ {"role": "assistant", "content": ai_message}
151
+ )
152
+
153
+ doc_meta = thread_document_metadata(thread_key)
154
+ if doc_meta:
155
+ st.caption(
156
+ f"Document indexed: {doc_meta.get('filename')} "
157
+ f"(chunks: {doc_meta.get('chunks')}, pages: {doc_meta.get('documents')})"
158
+ )
159
+
160
+ st.divider()
161
+
162
+ if selected_thread:
163
+ st.session_state["thread_id"] = selected_thread
164
+ messages = load_conversation(selected_thread)
165
+
166
+ temp_messages = []
167
+ for msg in messages:
168
+ role = "user" if isinstance(msg, HumanMessage) else "assistant"
169
+ temp_messages.append({"role": role, "content": msg.content})
170
+ st.session_state["message_history"] = temp_messages
171
+ st.session_state["ingested_docs"].setdefault(str(selected_thread), {})
172
+ st.rerun()